@notectl/core 2.2.6 → 2.3.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (544) hide show
  1. package/README.md +1 -1
  2. package/THIRD-PARTY-NOTICES.md +129 -0
  3. package/dist/chunks/{AlignmentPlugin-DeD4C4EP.mjs → AlignmentPlugin-C9Rr_R-g.mjs} +2 -2
  4. package/dist/chunks/{AlignmentPlugin-DeD4C4EP.mjs.map → AlignmentPlugin-C9Rr_R-g.mjs.map} +1 -1
  5. package/dist/chunks/{AttrRegistry-DcDVyzLm.mjs → AttrRegistry-B3zB02z9.mjs} +2 -2
  6. package/dist/chunks/AttrRegistry-B3zB02z9.mjs.map +1 -0
  7. package/dist/chunks/AttributedMarkCommands-BCvmqeFZ.mjs +2 -0
  8. package/dist/chunks/{AttributedMarkCommands-D4W2Jgpj.mjs.map → AttributedMarkCommands-BCvmqeFZ.mjs.map} +1 -1
  9. package/dist/chunks/{BidiIsolationPlugin-BddRbDCN.mjs → BidiIsolationPlugin-Cw2KMk-H.mjs} +2 -2
  10. package/dist/chunks/{BidiIsolationPlugin-BddRbDCN.mjs.map → BidiIsolationPlugin-Cw2KMk-H.mjs.map} +1 -1
  11. package/dist/chunks/BlockInsertion-CYH2gRkY.mjs +2 -0
  12. package/dist/chunks/BlockInsertion-CYH2gRkY.mjs.map +1 -0
  13. package/dist/chunks/BlockquotePlugin-0bZSbkyo.mjs +2 -0
  14. package/dist/chunks/{BlockquotePlugin-4V7KV_Sb.mjs.map → BlockquotePlugin-0bZSbkyo.mjs.map} +1 -1
  15. package/dist/chunks/CaretNavigationPlugin-BPZ9b6XR.mjs +2 -0
  16. package/dist/chunks/CaretNavigationPlugin-BPZ9b6XR.mjs.map +1 -0
  17. package/dist/chunks/CodeBlockPlugin-BCJ3faXx.mjs +2 -0
  18. package/dist/chunks/CodeBlockPlugin-BCJ3faXx.mjs.map +1 -0
  19. package/dist/chunks/{ColorGrid-DPNiXxpD.mjs → ColorGrid-DQEkJ-0y.mjs} +2 -2
  20. package/dist/chunks/{ColorGrid-DPNiXxpD.mjs.map → ColorGrid-DQEkJ-0y.mjs.map} +1 -1
  21. package/dist/chunks/{ColorPickerPopup-lcf3jS6G.mjs → ColorPickerPopup-CyF26zIU.mjs} +2 -2
  22. package/dist/chunks/{ColorPickerPopup-lcf3jS6G.mjs.map → ColorPickerPopup-CyF26zIU.mjs.map} +1 -1
  23. package/dist/chunks/Commands-D5ND50PQ.mjs +2 -0
  24. package/dist/chunks/Commands-D5ND50PQ.mjs.map +1 -0
  25. package/dist/chunks/ContentModel-NpAj7vGW.mjs +2 -0
  26. package/dist/chunks/ContentModel-NpAj7vGW.mjs.map +1 -0
  27. package/dist/chunks/Decoration-BOP1TAUd.mjs +2 -0
  28. package/dist/chunks/Decoration-BOP1TAUd.mjs.map +1 -0
  29. package/dist/chunks/{DirectionDetection-C7XE0nxW.mjs → DirectionDetection-CDVSEWQ6.mjs} +2 -2
  30. package/dist/chunks/{DirectionDetection-C7XE0nxW.mjs.map → DirectionDetection-CDVSEWQ6.mjs.map} +1 -1
  31. package/dist/chunks/Document-827l3P80.mjs +2 -0
  32. package/dist/chunks/Document-827l3P80.mjs.map +1 -0
  33. package/dist/chunks/DocumentParser-D2tr3ZKn.mjs +2 -0
  34. package/dist/chunks/DocumentParser-D2tr3ZKn.mjs.map +1 -0
  35. package/dist/chunks/EditorEventBoundary-zpYRxryo.mjs +2 -0
  36. package/dist/chunks/EditorEventBoundary-zpYRxryo.mjs.map +1 -0
  37. package/dist/chunks/{FontPlugin-DQMj65Bc.mjs → FontPlugin-D041tiLe.mjs} +2 -2
  38. package/dist/chunks/{FontPlugin-DQMj65Bc.mjs.map → FontPlugin-D041tiLe.mjs.map} +1 -1
  39. package/dist/chunks/{FontSizePlugin-9StCjEfN.mjs → FontSizePlugin-8CAvj1RD.mjs} +2 -2
  40. package/dist/chunks/FontSizePlugin-8CAvj1RD.mjs.map +1 -0
  41. package/dist/chunks/FormulaPlugin-DJ39BtqV.mjs +2 -0
  42. package/dist/chunks/FormulaPlugin-DJ39BtqV.mjs.map +1 -0
  43. package/dist/chunks/GapCursorNavigation-DCWOmopl.mjs +2 -0
  44. package/dist/chunks/{GapCursorNavigation-ycNzuQVH.mjs.map → GapCursorNavigation-DCWOmopl.mjs.map} +1 -1
  45. package/dist/chunks/GapCursorPlugin-2iR6506y.mjs +2 -0
  46. package/dist/chunks/{GapCursorPlugin-Zvxjnr82.mjs.map → GapCursorPlugin-2iR6506y.mjs.map} +1 -1
  47. package/dist/chunks/HTMLUtils-Bhg3_P8B.mjs +2 -0
  48. package/dist/chunks/HTMLUtils-Bhg3_P8B.mjs.map +1 -0
  49. package/dist/chunks/{HardBreakPlugin-9DOyCyyM.mjs → HardBreakPlugin-vniSvTgq.mjs} +2 -2
  50. package/dist/chunks/{HardBreakPlugin-9DOyCyyM.mjs.map → HardBreakPlugin-vniSvTgq.mjs.map} +1 -1
  51. package/dist/chunks/HeadingPlugin-DUKsLuMd.mjs +2 -0
  52. package/dist/chunks/{HeadingPlugin-BuGoM9Rz.mjs.map → HeadingPlugin-DUKsLuMd.mjs.map} +1 -1
  53. package/dist/chunks/{HighlightPlugin-C6pHifVz.mjs → HighlightPlugin-DRTAE1N5.mjs} +2 -2
  54. package/dist/chunks/{HighlightPlugin-C6pHifVz.mjs.map → HighlightPlugin-DRTAE1N5.mjs.map} +1 -1
  55. package/dist/chunks/HorizontalRulePlugin-B9OvwrKB.mjs +2 -0
  56. package/dist/chunks/HorizontalRulePlugin-B9OvwrKB.mjs.map +1 -0
  57. package/dist/chunks/ImagePlugin-CwxTRr6d.mjs +2 -0
  58. package/dist/chunks/{ImagePlugin-KpkuE2LH.mjs.map → ImagePlugin-CwxTRr6d.mjs.map} +1 -1
  59. package/dist/chunks/{InlineCodePlugin-DMr4O7c7.mjs → InlineCodePlugin-uxgMUX_E.mjs} +2 -2
  60. package/dist/chunks/InlineCodePlugin-uxgMUX_E.mjs.map +1 -0
  61. package/dist/chunks/InlineStyleMarkSpec-CjSRj4f_.mjs +2 -0
  62. package/dist/chunks/{InlineStyleMarkSpec-C6LJT7kp.mjs.map → InlineStyleMarkSpec-CjSRj4f_.mjs.map} +1 -1
  63. package/dist/chunks/LinkPlugin-CvWHbSkb.mjs +2 -0
  64. package/dist/chunks/LinkPlugin-CvWHbSkb.mjs.map +1 -0
  65. package/dist/chunks/ListPlugin-BchSFWVn.mjs +2 -0
  66. package/dist/chunks/ListPlugin-BchSFWVn.mjs.map +1 -0
  67. package/dist/chunks/MarkInputRule-Bdi8KPus.mjs +2 -0
  68. package/dist/chunks/MarkInputRule-Bdi8KPus.mjs.map +1 -0
  69. package/dist/chunks/MarkdownHTMLRegistry-Q7l0d6Ma.mjs +2 -0
  70. package/dist/chunks/MarkdownHTMLRegistry-Q7l0d6Ma.mjs.map +1 -0
  71. package/dist/chunks/MarkdownParser-Dp62mfUq.mjs +2 -0
  72. package/dist/chunks/MarkdownParser-Dp62mfUq.mjs.map +1 -0
  73. package/dist/chunks/MarkdownSerializer-DBELFAeo.mjs +2 -0
  74. package/dist/chunks/MarkdownSerializer-DBELFAeo.mjs.map +1 -0
  75. package/dist/chunks/MathFont-BS8IwYh2.mjs +2 -0
  76. package/dist/chunks/MathFont-BS8IwYh2.mjs.map +1 -0
  77. package/dist/chunks/{NodeResolver-ChgLF_IP.mjs → NodeResolver-Dleih-8R.mjs} +2 -2
  78. package/dist/chunks/{NodeResolver-ChgLF_IP.mjs.map → NodeResolver-Dleih-8R.mjs.map} +1 -1
  79. package/dist/chunks/NodeSelectionCommands-WH5snxr_.mjs +2 -0
  80. package/dist/chunks/{NodeSelectionCommands-Dj4VxLdD.mjs.map → NodeSelectionCommands-WH5snxr_.mjs.map} +1 -1
  81. package/dist/chunks/{PopupManager-DUtaK3WX.mjs → PopupManager-Cj86uDEB.mjs} +2 -2
  82. package/dist/chunks/{PopupManager-DUtaK3WX.mjs.map → PopupManager-Cj86uDEB.mjs.map} +1 -1
  83. package/dist/chunks/PopupPositioning-BFh6Ed1D.mjs +2 -0
  84. package/dist/chunks/{PopupPositioning-BB97-__N.mjs.map → PopupPositioning-BFh6Ed1D.mjs.map} +1 -1
  85. package/dist/chunks/PrintPlugin-D2javl_d.mjs +2 -0
  86. package/dist/chunks/PrintPlugin-D2javl_d.mjs.map +1 -0
  87. package/dist/chunks/{RangeIterator-o8v3msQe.mjs → RangeIterator-DP7Ud3Gp.mjs} +2 -2
  88. package/dist/chunks/{RangeIterator-o8v3msQe.mjs.map → RangeIterator-DP7Ud3Gp.mjs.map} +1 -1
  89. package/dist/chunks/SchemaRegistry-CkBN-1yW.mjs +2 -0
  90. package/dist/chunks/SchemaRegistry-CkBN-1yW.mjs.map +1 -0
  91. package/dist/chunks/SimpleMark-gTQaSJcO.mjs +2 -0
  92. package/dist/chunks/{SimpleMark-CaQtFAau.mjs.map → SimpleMark-gTQaSJcO.mjs.map} +1 -1
  93. package/dist/chunks/SmartPastePlugin-BvJQ-fOz.mjs +2 -0
  94. package/dist/chunks/SmartPastePlugin-BvJQ-fOz.mjs.map +1 -0
  95. package/dist/chunks/StarterFonts-BDQPg-cu.mjs +2 -0
  96. package/dist/chunks/StarterFonts-BDQPg-cu.mjs.map +1 -0
  97. package/dist/chunks/StrikethroughPlugin-BdrG1TTY.mjs +2 -0
  98. package/dist/chunks/StrikethroughPlugin-BdrG1TTY.mjs.map +1 -0
  99. package/dist/chunks/StyleRuntime-DW6omotc.mjs +2 -0
  100. package/dist/chunks/StyleRuntime-DW6omotc.mjs.map +1 -0
  101. package/dist/chunks/{SuperSubPlugin-DVP7VnIz.mjs → SuperSubPlugin-DTZB0Y3D.mjs} +2 -2
  102. package/dist/chunks/{SuperSubPlugin-DVP7VnIz.mjs.map → SuperSubPlugin-DTZB0Y3D.mjs.map} +1 -1
  103. package/dist/chunks/TableDimensions-BBhjHNjQ.mjs +2 -0
  104. package/dist/chunks/TableDimensions-BBhjHNjQ.mjs.map +1 -0
  105. package/dist/chunks/TablePlugin-CPvg9YZS.mjs +2 -0
  106. package/dist/chunks/TablePlugin-CPvg9YZS.mjs.map +1 -0
  107. package/dist/chunks/TextColorPlugin-Ckg3KWvb.mjs +2 -0
  108. package/dist/chunks/{TextColorPlugin-CEfZQ6Md.mjs.map → TextColorPlugin-Ckg3KWvb.mjs.map} +1 -1
  109. package/dist/chunks/TextDirectionAutoPlugin-DRGbgTlx.mjs +2 -0
  110. package/dist/chunks/{TextDirectionAutoPlugin-CzWJjrvG.mjs.map → TextDirectionAutoPlugin-DRGbgTlx.mjs.map} +1 -1
  111. package/dist/chunks/TextDirectionPlugin-BCeYyJHo.mjs +2 -0
  112. package/dist/chunks/{TextDirectionPlugin-DHB88HKf.mjs.map → TextDirectionPlugin-BCeYyJHo.mjs.map} +1 -1
  113. package/dist/chunks/TextFormattingPlugin-BhRxSC8q.mjs +2 -0
  114. package/dist/chunks/TextFormattingPlugin-BhRxSC8q.mjs.map +1 -0
  115. package/dist/chunks/ThemeEngine-BUVo_zaT.mjs +3 -0
  116. package/dist/chunks/ThemeEngine-BUVo_zaT.mjs.map +1 -0
  117. package/dist/chunks/ToolbarPlugin-dmTj1jIz.mjs +2 -0
  118. package/dist/chunks/{ToolbarPlugin-DVGrFf8v.mjs.map → ToolbarPlugin-dmTj1jIz.mjs.map} +1 -1
  119. package/dist/chunks/VideoPlugin-BugkI7-m.mjs +2 -0
  120. package/dist/chunks/VideoPlugin-BugkI7-m.mjs.map +1 -0
  121. package/dist/chunks/WordBoundary-CFpIJDNP.mjs +2 -0
  122. package/dist/chunks/{WordBoundary-DxeMBRyP.mjs.map → WordBoundary-CFpIJDNP.mjs.map} +1 -1
  123. package/dist/chunks/XmlSupport-DIXH5on9.mjs +2 -0
  124. package/dist/chunks/XmlSupport-DIXH5on9.mjs.map +1 -0
  125. package/dist/chunks/ar-Dg9PdDet.mjs +2 -0
  126. package/dist/chunks/ar-Dg9PdDet.mjs.map +1 -0
  127. package/dist/chunks/ar-eOA3UmiE.mjs +2 -0
  128. package/dist/chunks/{ar-BTShmP2E.mjs.map → ar-eOA3UmiE.mjs.map} +1 -1
  129. package/dist/chunks/de-DJ5EkXQo.mjs +2 -0
  130. package/dist/chunks/de-DJ5EkXQo.mjs.map +1 -0
  131. package/dist/chunks/{de-C--bRmjW.mjs → de-DRbhnS4T.mjs} +2 -2
  132. package/dist/chunks/{de-C--bRmjW.mjs.map → de-DRbhnS4T.mjs.map} +1 -1
  133. package/dist/chunks/{es-DFUVd7eO.mjs → es-BQ9dox_E.mjs} +2 -2
  134. package/dist/chunks/{es-DFUVd7eO.mjs.map → es-BQ9dox_E.mjs.map} +1 -1
  135. package/dist/chunks/es-CEAJj7aB.mjs +2 -0
  136. package/dist/chunks/es-CEAJj7aB.mjs.map +1 -0
  137. package/dist/chunks/fr-DhWQzZy3.mjs +2 -0
  138. package/dist/chunks/fr-DhWQzZy3.mjs.map +1 -0
  139. package/dist/chunks/{fr-BaXKyPmX.mjs → fr-NVOinLyF.mjs} +2 -2
  140. package/dist/chunks/{fr-BaXKyPmX.mjs.map → fr-NVOinLyF.mjs.map} +1 -1
  141. package/dist/chunks/full-JM0-SwWy.mjs +2 -0
  142. package/dist/chunks/{full-BBl7mvwH.mjs.map → full-JM0-SwWy.mjs.map} +1 -1
  143. package/dist/chunks/hi-BsZzSMfL.mjs +2 -0
  144. package/dist/chunks/hi-BsZzSMfL.mjs.map +1 -0
  145. package/dist/chunks/{hi-aH9HZG23.mjs → hi-DrC2H81d.mjs} +2 -2
  146. package/dist/chunks/{hi-aH9HZG23.mjs.map → hi-DrC2H81d.mjs.map} +1 -1
  147. package/dist/chunks/minimal-DSlR2A27.mjs +2 -0
  148. package/dist/chunks/{minimal-CtnR4dqp.mjs.map → minimal-DSlR2A27.mjs.map} +1 -1
  149. package/dist/chunks/pt-BuZ7acHF.mjs +2 -0
  150. package/dist/chunks/pt-BuZ7acHF.mjs.map +1 -0
  151. package/dist/chunks/{pt-Hy-0Xnnc.mjs → pt-CFrcl1v_.mjs} +2 -2
  152. package/dist/chunks/{pt-Hy-0Xnnc.mjs.map → pt-CFrcl1v_.mjs.map} +1 -1
  153. package/dist/chunks/register-BjsdJ3Aq.mjs +2 -0
  154. package/dist/chunks/register-BjsdJ3Aq.mjs.map +1 -0
  155. package/dist/chunks/rolldown-runtime-H_PjY6_i.mjs +1 -0
  156. package/dist/chunks/ru-CsP6mLxp.mjs +2 -0
  157. package/dist/chunks/ru-CsP6mLxp.mjs.map +1 -0
  158. package/dist/chunks/{ru-BFpEOrVp.mjs → ru-gxbzqLL8.mjs} +2 -2
  159. package/dist/chunks/{ru-BFpEOrVp.mjs.map → ru-gxbzqLL8.mjs.map} +1 -1
  160. package/dist/chunks/src-5GKFQ2mQ.mjs +2 -0
  161. package/dist/chunks/src-5GKFQ2mQ.mjs.map +1 -0
  162. package/dist/chunks/xml-BsV44TrJ.mjs +2 -0
  163. package/dist/chunks/xml-BsV44TrJ.mjs.map +1 -0
  164. package/dist/chunks/zh-BFZOM3lF.mjs +2 -0
  165. package/dist/chunks/{zh-BjoyjClN.mjs.map → zh-BFZOM3lF.mjs.map} +1 -1
  166. package/dist/chunks/zh-CiIyOm6U.mjs +2 -0
  167. package/dist/chunks/zh-CiIyOm6U.mjs.map +1 -0
  168. package/dist/commands/BlockInsertion.d.ts +5 -3
  169. package/dist/commands/BlockInsertion.d.ts.map +1 -1
  170. package/dist/commands/SelectionDeletion.d.ts +13 -2
  171. package/dist/commands/SelectionDeletion.d.ts.map +1 -1
  172. package/dist/editor/ContentSerializer.d.ts +21 -0
  173. package/dist/editor/ContentSerializer.d.ts.map +1 -1
  174. package/dist/editor/EditorConfig.d.ts +17 -0
  175. package/dist/editor/EditorConfig.d.ts.map +1 -1
  176. package/dist/editor/EditorConfigController.d.ts +10 -0
  177. package/dist/editor/EditorConfigController.d.ts.map +1 -1
  178. package/dist/editor/EditorInitializer.d.ts +4 -0
  179. package/dist/editor/EditorInitializer.d.ts.map +1 -1
  180. package/dist/editor/EditorLocale.d.ts +2 -0
  181. package/dist/editor/EditorLocale.d.ts.map +1 -1
  182. package/dist/editor/MarkdownMode.d.ts +46 -0
  183. package/dist/editor/MarkdownMode.d.ts.map +1 -0
  184. package/dist/editor/NotectlEditor.d.ts +24 -0
  185. package/dist/editor/NotectlEditor.d.ts.map +1 -1
  186. package/dist/editor/locales/ar.d.ts.map +1 -1
  187. package/dist/editor/locales/de.d.ts.map +1 -1
  188. package/dist/editor/locales/es.d.ts.map +1 -1
  189. package/dist/editor/locales/fr.d.ts.map +1 -1
  190. package/dist/editor/locales/hi.d.ts.map +1 -1
  191. package/dist/editor/locales/pt.d.ts.map +1 -1
  192. package/dist/editor/locales/ru.d.ts.map +1 -1
  193. package/dist/editor/locales/zh.d.ts.map +1 -1
  194. package/dist/editor/styles/list.d.ts +1 -1
  195. package/dist/editor/styles/list.d.ts.map +1 -1
  196. package/dist/editor/styles/table.d.ts +1 -1
  197. package/dist/editor/styles/table.d.ts.map +1 -1
  198. package/dist/fonts/math.d.ts +3 -0
  199. package/dist/fonts/math.d.ts.map +1 -0
  200. package/dist/fonts/math.mjs +1 -0
  201. package/dist/fonts/starter.d.ts +3 -0
  202. package/dist/fonts/starter.d.ts.map +1 -0
  203. package/dist/fonts/starter.mjs +1 -0
  204. package/dist/fonts.d.ts +4 -4
  205. package/dist/fonts.mjs +1 -1
  206. package/dist/full.d.ts +1 -1
  207. package/dist/full.mjs +1 -1
  208. package/dist/html.d.ts +1 -0
  209. package/dist/html.d.ts.map +1 -1
  210. package/dist/html.mjs +1 -1
  211. package/dist/index.d.ts +7 -6
  212. package/dist/index.d.ts.map +1 -1
  213. package/dist/input/ClipboardHandler.d.ts +2 -0
  214. package/dist/input/ClipboardHandler.d.ts.map +1 -1
  215. package/dist/input/InputHandler.d.ts +7 -0
  216. package/dist/input/InputHandler.d.ts.map +1 -1
  217. package/dist/input/InputManager.d.ts +10 -0
  218. package/dist/input/InputManager.d.ts.map +1 -1
  219. package/dist/input/KeyboardHandler.d.ts.map +1 -1
  220. package/dist/input/MarkdownPasteDetector.d.ts +26 -0
  221. package/dist/input/MarkdownPasteDetector.d.ts.map +1 -0
  222. package/dist/input/PasteHTMLHandler.d.ts +18 -1
  223. package/dist/input/PasteHTMLHandler.d.ts.map +1 -1
  224. package/dist/input/PasteHandler.d.ts +30 -0
  225. package/dist/input/PasteHandler.d.ts.map +1 -1
  226. package/dist/input/PasteRichBlockHandler.d.ts.map +1 -1
  227. package/dist/input/SelectionDocument.d.ts +2 -1
  228. package/dist/input/SelectionDocument.d.ts.map +1 -1
  229. package/dist/markdown.d.ts +17 -0
  230. package/dist/markdown.d.ts.map +1 -0
  231. package/dist/markdown.mjs +1 -0
  232. package/dist/model/AttrRegistry.d.ts +2 -2
  233. package/dist/model/AttrRegistry.d.ts.map +1 -1
  234. package/dist/model/ContentModel.d.ts +12 -0
  235. package/dist/model/ContentModel.d.ts.map +1 -1
  236. package/dist/model/Document.d.ts +28 -3
  237. package/dist/model/Document.d.ts.map +1 -1
  238. package/dist/model/HTMLUtils.d.ts +15 -0
  239. package/dist/model/HTMLUtils.d.ts.map +1 -1
  240. package/dist/model/InlineNodeSpec.d.ts +7 -1
  241. package/dist/model/InlineNodeSpec.d.ts.map +1 -1
  242. package/dist/model/InputRule.d.ts +11 -0
  243. package/dist/model/InputRule.d.ts.map +1 -1
  244. package/dist/model/MarkSpec.d.ts +7 -1
  245. package/dist/model/MarkSpec.d.ts.map +1 -1
  246. package/dist/model/MarkdownSyntaxRegistry.d.ts +51 -0
  247. package/dist/model/MarkdownSyntaxRegistry.d.ts.map +1 -0
  248. package/dist/model/NodeSpec.d.ts +47 -1
  249. package/dist/model/NodeSpec.d.ts.map +1 -1
  250. package/dist/model/RichBlockData.d.ts +2 -0
  251. package/dist/model/RichBlockData.d.ts.map +1 -1
  252. package/dist/model/SchemaRegistry.d.ts.map +1 -1
  253. package/dist/model/TableDimensions.d.ts +11 -0
  254. package/dist/model/TableDimensions.d.ts.map +1 -0
  255. package/dist/notectl-core.mjs +1 -1
  256. package/dist/notectl-core.umd.js +1 -1
  257. package/dist/notectl-core.umd.js.map +1 -1
  258. package/dist/platform/EditorEventBoundary.d.ts +12 -0
  259. package/dist/platform/EditorEventBoundary.d.ts.map +1 -0
  260. package/dist/plugins/Plugin.d.ts +7 -0
  261. package/dist/plugins/Plugin.d.ts.map +1 -1
  262. package/dist/plugins/PluginContextFactory.d.ts +2 -0
  263. package/dist/plugins/PluginContextFactory.d.ts.map +1 -1
  264. package/dist/plugins/PluginManager.d.ts +2 -0
  265. package/dist/plugins/PluginManager.d.ts.map +1 -1
  266. package/dist/plugins/alignment.mjs +1 -1
  267. package/dist/plugins/bidi-isolation.mjs +1 -1
  268. package/dist/plugins/blockquote/BlockquotePlugin.d.ts +2 -0
  269. package/dist/plugins/blockquote/BlockquotePlugin.d.ts.map +1 -1
  270. package/dist/plugins/blockquote.mjs +1 -1
  271. package/dist/plugins/caret-navigation.mjs +1 -1
  272. package/dist/plugins/code-block/CodeBlockHighlighting.d.ts.map +1 -1
  273. package/dist/plugins/code-block/CodeBlockTypes.d.ts +2 -0
  274. package/dist/plugins/code-block/CodeBlockTypes.d.ts.map +1 -1
  275. package/dist/plugins/code-block.mjs +1 -1
  276. package/dist/plugins/font-size/FontSizeOperations.d.ts.map +1 -1
  277. package/dist/plugins/font-size.mjs +1 -1
  278. package/dist/plugins/font.mjs +1 -1
  279. package/dist/plugins/formula/DisplayMathNodeSpec.d.ts.map +1 -1
  280. package/dist/plugins/formula/FormulaInputRules.d.ts.map +1 -1
  281. package/dist/plugins/formula/FormulaMarkdownSyntax.d.ts +4 -0
  282. package/dist/plugins/formula/FormulaMarkdownSyntax.d.ts.map +1 -0
  283. package/dist/plugins/formula/FormulaPlugin.d.ts.map +1 -1
  284. package/dist/plugins/formula/FormulaTypes.d.ts +3 -1
  285. package/dist/plugins/formula/FormulaTypes.d.ts.map +1 -1
  286. package/dist/plugins/formula/InlineMathNodeSpec.d.ts.map +1 -1
  287. package/dist/plugins/formula.mjs +1 -1
  288. package/dist/plugins/gap-cursor.mjs +1 -1
  289. package/dist/plugins/hard-break.mjs +1 -1
  290. package/dist/plugins/heading/HeadingPlugin.d.ts +2 -0
  291. package/dist/plugins/heading/HeadingPlugin.d.ts.map +1 -1
  292. package/dist/plugins/heading.mjs +1 -1
  293. package/dist/plugins/highlight.mjs +1 -1
  294. package/dist/plugins/horizontal-rule/HorizontalRulePlugin.d.ts +2 -0
  295. package/dist/plugins/horizontal-rule/HorizontalRulePlugin.d.ts.map +1 -1
  296. package/dist/plugins/horizontal-rule.mjs +1 -1
  297. package/dist/plugins/image/ImagePlugin.d.ts +14 -0
  298. package/dist/plugins/image/ImagePlugin.d.ts.map +1 -1
  299. package/dist/plugins/image.mjs +1 -1
  300. package/dist/plugins/inline-code/InlineCodePlugin.d.ts.map +1 -1
  301. package/dist/plugins/inline-code.mjs +1 -1
  302. package/dist/plugins/language.mjs +1 -1
  303. package/dist/plugins/link/LinkPlugin.d.ts +14 -0
  304. package/dist/plugins/link/LinkPlugin.d.ts.map +1 -1
  305. package/dist/plugins/link.mjs +1 -1
  306. package/dist/plugins/list/ListCommands.d.ts +5 -1
  307. package/dist/plugins/list/ListCommands.d.ts.map +1 -1
  308. package/dist/plugins/list/ListInputRules.d.ts.map +1 -1
  309. package/dist/plugins/list/ListItemContext.d.ts +27 -0
  310. package/dist/plugins/list/ListItemContext.d.ts.map +1 -0
  311. package/dist/plugins/list/ListKeyboardHandlers.d.ts.map +1 -1
  312. package/dist/plugins/list/ListPlugin.d.ts +2 -0
  313. package/dist/plugins/list/ListPlugin.d.ts.map +1 -1
  314. package/dist/plugins/list/ListToolbarItems.d.ts.map +1 -1
  315. package/dist/plugins/list.mjs +1 -1
  316. package/dist/plugins/print/PrintContentPreparer.d.ts.map +1 -1
  317. package/dist/plugins/print/PrintDestinationBridge.d.ts +23 -0
  318. package/dist/plugins/print/PrintDestinationBridge.d.ts.map +1 -0
  319. package/dist/plugins/print/PrintHostStyles.d.ts.map +1 -1
  320. package/dist/plugins/print/PrintServiceImpl.d.ts +5 -1
  321. package/dist/plugins/print/PrintServiceImpl.d.ts.map +1 -1
  322. package/dist/plugins/print/PrintStyleCollector.d.ts.map +1 -1
  323. package/dist/plugins/print.mjs +1 -1
  324. package/dist/plugins/shared/MarkInputRule.d.ts +9 -0
  325. package/dist/plugins/shared/MarkInputRule.d.ts.map +1 -0
  326. package/dist/plugins/shared/PopupPositioning.d.ts +2 -0
  327. package/dist/plugins/shared/PopupPositioning.d.ts.map +1 -1
  328. package/dist/plugins/shared/index.d.ts +1 -0
  329. package/dist/plugins/shared/index.d.ts.map +1 -1
  330. package/dist/plugins/shared.mjs +1 -1
  331. package/dist/plugins/smart-paste/SmartPastePlugin.d.ts.map +1 -1
  332. package/dist/plugins/smart-paste.mjs +1 -1
  333. package/dist/plugins/strikethrough/StrikethroughPlugin.d.ts +2 -0
  334. package/dist/plugins/strikethrough/StrikethroughPlugin.d.ts.map +1 -1
  335. package/dist/plugins/strikethrough.mjs +1 -1
  336. package/dist/plugins/super-sub.mjs +1 -1
  337. package/dist/plugins/table/TableClipboard.d.ts +8 -0
  338. package/dist/plugins/table/TableClipboard.d.ts.map +1 -0
  339. package/dist/plugins/table/TableCommands.d.ts.map +1 -1
  340. package/dist/plugins/table/TableContextMenu.d.ts +11 -1
  341. package/dist/plugins/table/TableContextMenu.d.ts.map +1 -1
  342. package/dist/plugins/table/TableControls.d.ts +6 -1
  343. package/dist/plugins/table/TableControls.d.ts.map +1 -1
  344. package/dist/plugins/table/TableControlsDOM.d.ts +11 -2
  345. package/dist/plugins/table/TableControlsDOM.d.ts.map +1 -1
  346. package/dist/plugins/table/TableControlsLayout.d.ts +12 -3
  347. package/dist/plugins/table/TableControlsLayout.d.ts.map +1 -1
  348. package/dist/plugins/table/TableGrid.d.ts +57 -0
  349. package/dist/plugins/table/TableGrid.d.ts.map +1 -0
  350. package/dist/plugins/table/TableHelpers.d.ts +4 -0
  351. package/dist/plugins/table/TableHelpers.d.ts.map +1 -1
  352. package/dist/plugins/table/TableLocale.d.ts +30 -0
  353. package/dist/plugins/table/TableLocale.d.ts.map +1 -1
  354. package/dist/plugins/table/TableNavigation.d.ts +5 -1
  355. package/dist/plugins/table/TableNavigation.d.ts.map +1 -1
  356. package/dist/plugins/table/TableNodeViews.d.ts +13 -1
  357. package/dist/plugins/table/TableNodeViews.d.ts.map +1 -1
  358. package/dist/plugins/table/TablePlugin.d.ts +21 -1
  359. package/dist/plugins/table/TablePlugin.d.ts.map +1 -1
  360. package/dist/plugins/table/TableSelection.d.ts.map +1 -1
  361. package/dist/plugins/table/TableSizeEditor.d.ts +11 -0
  362. package/dist/plugins/table/TableSizeEditor.d.ts.map +1 -0
  363. package/dist/plugins/table/TableSizing.d.ts +70 -0
  364. package/dist/plugins/table/TableSizing.d.ts.map +1 -0
  365. package/dist/plugins/table/index.d.ts +3 -1
  366. package/dist/plugins/table/index.d.ts.map +1 -1
  367. package/dist/plugins/table/locales/ar.d.ts.map +1 -1
  368. package/dist/plugins/table/locales/de.d.ts.map +1 -1
  369. package/dist/plugins/table/locales/es.d.ts.map +1 -1
  370. package/dist/plugins/table/locales/fr.d.ts.map +1 -1
  371. package/dist/plugins/table/locales/hi.d.ts.map +1 -1
  372. package/dist/plugins/table/locales/pt.d.ts.map +1 -1
  373. package/dist/plugins/table/locales/ru.d.ts.map +1 -1
  374. package/dist/plugins/table/locales/zh.d.ts.map +1 -1
  375. package/dist/plugins/table.mjs +1 -1
  376. package/dist/plugins/text-color.mjs +1 -1
  377. package/dist/plugins/text-direction-auto.mjs +1 -1
  378. package/dist/plugins/text-direction.mjs +1 -1
  379. package/dist/plugins/text-formatting/TextFormattingPlugin.d.ts +9 -0
  380. package/dist/plugins/text-formatting/TextFormattingPlugin.d.ts.map +1 -1
  381. package/dist/plugins/text-formatting.mjs +1 -1
  382. package/dist/plugins/toolbar.mjs +1 -1
  383. package/dist/plugins/video/VideoCommands.d.ts.map +1 -1
  384. package/dist/plugins/video.mjs +1 -1
  385. package/dist/presets/full.d.ts +1 -1
  386. package/dist/presets/full.mjs +1 -1
  387. package/dist/presets/minimal.d.ts +1 -1
  388. package/dist/presets/minimal.mjs +1 -1
  389. package/dist/presets.d.ts +1 -1
  390. package/dist/presets.mjs +1 -1
  391. package/dist/register.d.ts +3 -0
  392. package/dist/register.d.ts.map +1 -0
  393. package/dist/register.mjs +1 -0
  394. package/dist/serialization/DocumentParser.d.ts.map +1 -1
  395. package/dist/serialization/DocumentSerializer.d.ts +2 -0
  396. package/dist/serialization/DocumentSerializer.d.ts.map +1 -1
  397. package/dist/serialization/HTMLSanitization.d.ts +15 -0
  398. package/dist/serialization/HTMLSanitization.d.ts.map +1 -0
  399. package/dist/serialization/MarkSerializer.d.ts +12 -0
  400. package/dist/serialization/MarkSerializer.d.ts.map +1 -1
  401. package/dist/serialization/MarkdownParser.d.ts +6 -0
  402. package/dist/serialization/MarkdownParser.d.ts.map +1 -0
  403. package/dist/serialization/MarkdownSerializer.d.ts +12 -0
  404. package/dist/serialization/MarkdownSerializer.d.ts.map +1 -0
  405. package/dist/serialization/MarkdownTypes.d.ts +59 -0
  406. package/dist/serialization/MarkdownTypes.d.ts.map +1 -0
  407. package/dist/serialization/TableDimensions.d.ts +37 -0
  408. package/dist/serialization/TableDimensions.d.ts.map +1 -0
  409. package/dist/serialization/markdown/BlockSerializers.d.ts +7 -0
  410. package/dist/serialization/markdown/BlockSerializers.d.ts.map +1 -0
  411. package/dist/serialization/markdown/BlockTokenizer.d.ts +54 -0
  412. package/dist/serialization/markdown/BlockTokenizer.d.ts.map +1 -0
  413. package/dist/serialization/markdown/GfmAutolink.d.ts +20 -0
  414. package/dist/serialization/markdown/GfmAutolink.d.ts.map +1 -0
  415. package/dist/serialization/markdown/GfmTableParser.d.ts +26 -0
  416. package/dist/serialization/markdown/GfmTableParser.d.ts.map +1 -0
  417. package/dist/serialization/markdown/InlineAst.d.ts +34 -0
  418. package/dist/serialization/markdown/InlineAst.d.ts.map +1 -0
  419. package/dist/serialization/markdown/InlineSerializers.d.ts +5 -0
  420. package/dist/serialization/markdown/InlineSerializers.d.ts.map +1 -0
  421. package/dist/serialization/markdown/InlineTokenizer.d.ts +5 -0
  422. package/dist/serialization/markdown/InlineTokenizer.d.ts.map +1 -0
  423. package/dist/serialization/markdown/LinkReferenceExtractor.d.ts +37 -0
  424. package/dist/serialization/markdown/LinkReferenceExtractor.d.ts.map +1 -0
  425. package/dist/serialization/markdown/MarkdownContext.d.ts +32 -0
  426. package/dist/serialization/markdown/MarkdownContext.d.ts.map +1 -0
  427. package/dist/serialization/markdown/MarkdownEntities.d.ts +33 -0
  428. package/dist/serialization/markdown/MarkdownEntities.d.ts.map +1 -0
  429. package/dist/serialization/markdown/MarkdownEscape.d.ts +33 -0
  430. package/dist/serialization/markdown/MarkdownEscape.d.ts.map +1 -0
  431. package/dist/serialization/markdown/MarkdownHTMLRegistry.d.ts +4 -0
  432. package/dist/serialization/markdown/MarkdownHTMLRegistry.d.ts.map +1 -0
  433. package/dist/serialization/markdown/MarkdownParseContext.d.ts +23 -0
  434. package/dist/serialization/markdown/MarkdownParseContext.d.ts.map +1 -0
  435. package/dist/state/Mapping.d.ts +33 -10
  436. package/dist/state/Mapping.d.ts.map +1 -1
  437. package/dist/state/StepApplication.d.ts +3 -1
  438. package/dist/state/StepApplication.d.ts.map +1 -1
  439. package/dist/state/StepHandlers.d.ts.map +1 -1
  440. package/dist/state/StepInversion.d.ts +2 -1
  441. package/dist/state/StepInversion.d.ts.map +1 -1
  442. package/dist/state/StepMapping.d.ts +3 -2
  443. package/dist/state/StepMapping.d.ts.map +1 -1
  444. package/dist/state/StepMaps.d.ts +3 -2
  445. package/dist/state/StepMaps.d.ts.map +1 -1
  446. package/dist/state/Steps.d.ts +34 -2
  447. package/dist/state/Steps.d.ts.map +1 -1
  448. package/dist/state/TransactionBuilder.d.ts +7 -1
  449. package/dist/state/TransactionBuilder.d.ts.map +1 -1
  450. package/dist/test/MarkdownConformanceUtils.d.ts +12 -0
  451. package/dist/test/MarkdownConformanceUtils.d.ts.map +1 -0
  452. package/dist/view/BlockRendering.d.ts +5 -0
  453. package/dist/view/BlockRendering.d.ts.map +1 -1
  454. package/dist/view/DecorationRendering.d.ts +6 -0
  455. package/dist/view/DecorationRendering.d.ts.map +1 -1
  456. package/dist/view/EditorViewEvents.d.ts.map +1 -1
  457. package/dist/view/Reconciler.d.ts.map +1 -1
  458. package/package.json +28 -214
  459. package/dist/chunks/AttrRegistry-DcDVyzLm.mjs.map +0 -1
  460. package/dist/chunks/AttributedMarkCommands-D4W2Jgpj.mjs +0 -2
  461. package/dist/chunks/BlockInsertion-6rR9tIGP.mjs +0 -2
  462. package/dist/chunks/BlockInsertion-6rR9tIGP.mjs.map +0 -1
  463. package/dist/chunks/BlockquotePlugin-4V7KV_Sb.mjs +0 -2
  464. package/dist/chunks/CaretNavigationPlugin-C6XBwp0N.mjs +0 -2
  465. package/dist/chunks/CaretNavigationPlugin-C6XBwp0N.mjs.map +0 -1
  466. package/dist/chunks/CodeBlockPlugin-3V2K3RBe.mjs +0 -2
  467. package/dist/chunks/CodeBlockPlugin-3V2K3RBe.mjs.map +0 -1
  468. package/dist/chunks/Commands-BIIpx_Zd.mjs +0 -2
  469. package/dist/chunks/Commands-BIIpx_Zd.mjs.map +0 -1
  470. package/dist/chunks/Decoration-ZeyVfwJB.mjs +0 -2
  471. package/dist/chunks/Decoration-ZeyVfwJB.mjs.map +0 -1
  472. package/dist/chunks/Document-r7vLOAGA.mjs +0 -2
  473. package/dist/chunks/Document-r7vLOAGA.mjs.map +0 -1
  474. package/dist/chunks/DocumentParser-CcTSeT1B.mjs +0 -2
  475. package/dist/chunks/DocumentParser-CcTSeT1B.mjs.map +0 -1
  476. package/dist/chunks/FontSizePlugin-9StCjEfN.mjs.map +0 -1
  477. package/dist/chunks/FormulaPlugin-CV5VUxkb.mjs +0 -2
  478. package/dist/chunks/FormulaPlugin-CV5VUxkb.mjs.map +0 -1
  479. package/dist/chunks/GapCursorNavigation-ycNzuQVH.mjs +0 -2
  480. package/dist/chunks/GapCursorPlugin-Zvxjnr82.mjs +0 -2
  481. package/dist/chunks/HTMLUtils-C6B4UT00.mjs +0 -2
  482. package/dist/chunks/HTMLUtils-C6B4UT00.mjs.map +0 -1
  483. package/dist/chunks/HeadingPlugin-BuGoM9Rz.mjs +0 -2
  484. package/dist/chunks/HorizontalRulePlugin-0FjHPZuA.mjs +0 -2
  485. package/dist/chunks/HorizontalRulePlugin-0FjHPZuA.mjs.map +0 -1
  486. package/dist/chunks/ImagePlugin-KpkuE2LH.mjs +0 -2
  487. package/dist/chunks/InlineCodePlugin-DMr4O7c7.mjs.map +0 -1
  488. package/dist/chunks/InlineStyleMarkSpec-C6LJT7kp.mjs +0 -2
  489. package/dist/chunks/LinkPlugin-DvZ3MPgL.mjs +0 -2
  490. package/dist/chunks/LinkPlugin-DvZ3MPgL.mjs.map +0 -1
  491. package/dist/chunks/ListPlugin-2yl6KiTK.mjs +0 -2
  492. package/dist/chunks/ListPlugin-2yl6KiTK.mjs.map +0 -1
  493. package/dist/chunks/NodeSelectionCommands-Dj4VxLdD.mjs +0 -2
  494. package/dist/chunks/PopupPositioning-BB97-__N.mjs +0 -2
  495. package/dist/chunks/PrintPlugin-DyIZDY3Q.mjs +0 -2
  496. package/dist/chunks/PrintPlugin-DyIZDY3Q.mjs.map +0 -1
  497. package/dist/chunks/PrintTypes-CxU69qu3.mjs +0 -3
  498. package/dist/chunks/PrintTypes-CxU69qu3.mjs.map +0 -1
  499. package/dist/chunks/SimpleMark-CaQtFAau.mjs +0 -2
  500. package/dist/chunks/SmartPastePlugin-Bi_wpTCV.mjs +0 -2
  501. package/dist/chunks/SmartPastePlugin-Bi_wpTCV.mjs.map +0 -1
  502. package/dist/chunks/StrikethroughPlugin-BLKDRWtf.mjs +0 -2
  503. package/dist/chunks/StrikethroughPlugin-BLKDRWtf.mjs.map +0 -1
  504. package/dist/chunks/StyleRuntime-BFKu52mS.mjs +0 -2
  505. package/dist/chunks/StyleRuntime-BFKu52mS.mjs.map +0 -1
  506. package/dist/chunks/TablePlugin-BTH9VRZq.mjs +0 -2
  507. package/dist/chunks/TablePlugin-BTH9VRZq.mjs.map +0 -1
  508. package/dist/chunks/TextColorPlugin-CEfZQ6Md.mjs +0 -2
  509. package/dist/chunks/TextDirectionAutoPlugin-CzWJjrvG.mjs +0 -2
  510. package/dist/chunks/TextDirectionPlugin-DHB88HKf.mjs +0 -2
  511. package/dist/chunks/TextFormattingPlugin-Cubp3e7f.mjs +0 -2
  512. package/dist/chunks/TextFormattingPlugin-Cubp3e7f.mjs.map +0 -1
  513. package/dist/chunks/ToolbarPlugin-DVGrFf8v.mjs +0 -2
  514. package/dist/chunks/VideoPlugin-B3uf1Dwp.mjs +0 -2
  515. package/dist/chunks/VideoPlugin-B3uf1Dwp.mjs.map +0 -1
  516. package/dist/chunks/WordBoundary-DxeMBRyP.mjs +0 -2
  517. package/dist/chunks/XmlDetector-D7TQpw-e.mjs +0 -2
  518. package/dist/chunks/XmlDetector-D7TQpw-e.mjs.map +0 -1
  519. package/dist/chunks/XmlSupport-BYiRwlkK.mjs +0 -2
  520. package/dist/chunks/XmlSupport-BYiRwlkK.mjs.map +0 -1
  521. package/dist/chunks/ar-BTShmP2E.mjs +0 -2
  522. package/dist/chunks/ar-jbplYWkC.mjs +0 -2
  523. package/dist/chunks/ar-jbplYWkC.mjs.map +0 -1
  524. package/dist/chunks/de-DN-e6G5A.mjs +0 -2
  525. package/dist/chunks/de-DN-e6G5A.mjs.map +0 -1
  526. package/dist/chunks/es-CM55WeEN.mjs +0 -2
  527. package/dist/chunks/es-CM55WeEN.mjs.map +0 -1
  528. package/dist/chunks/fonts-DQC6Uj4r.mjs +0 -2
  529. package/dist/chunks/fonts-DQC6Uj4r.mjs.map +0 -1
  530. package/dist/chunks/fr-C_2i5Ono.mjs +0 -2
  531. package/dist/chunks/fr-C_2i5Ono.mjs.map +0 -1
  532. package/dist/chunks/full-BBl7mvwH.mjs +0 -2
  533. package/dist/chunks/hi-C9fvG91d.mjs +0 -2
  534. package/dist/chunks/hi-C9fvG91d.mjs.map +0 -1
  535. package/dist/chunks/minimal-CtnR4dqp.mjs +0 -2
  536. package/dist/chunks/pt-GqLw5tN0.mjs +0 -2
  537. package/dist/chunks/pt-GqLw5tN0.mjs.map +0 -1
  538. package/dist/chunks/ru-4g_qsaLr.mjs +0 -2
  539. package/dist/chunks/ru-4g_qsaLr.mjs.map +0 -1
  540. package/dist/chunks/src-C89Cw7ni.mjs +0 -2
  541. package/dist/chunks/src-C89Cw7ni.mjs.map +0 -1
  542. package/dist/chunks/zh-BjoyjClN.mjs +0 -2
  543. package/dist/chunks/zh-DeZP08HI.mjs +0 -2
  544. package/dist/chunks/zh-DeZP08HI.mjs.map +0 -1
package/README.md CHANGED
@@ -92,7 +92,7 @@ Full preset (toolbar, headings, lists, links, tables, code blocks, images, fonts
92
92
 
93
93
  ```ts
94
94
  import { ThemePreset, createEditor } from '@notectl/core';
95
- import { STARTER_FONTS } from '@notectl/core/fonts';
95
+ import { STARTER_FONTS } from '@notectl/core/fonts/starter';
96
96
  import { ToolbarOverflowBehavior } from '@notectl/core/plugins/toolbar';
97
97
  import { createFullPreset } from '@notectl/core/presets/full';
98
98
 
@@ -0,0 +1,129 @@
1
+ # Third-party notices
2
+
3
+ `@notectl/core` has a single runtime dependency (`dompurify`). It also bundles
4
+ three self-hosted font assets, distributed here for completeness.
5
+
6
+ ## Starter fonts (bundled WOFF2)
7
+
8
+ `FIRA_CODE`, `FIRA_SANS`, and `STARTER_FONTS` from
9
+ `@notectl/core/fonts/starter` contain **Fira Code** and **Fira Sans**. Both are
10
+ licensed under the **SIL Open Font License, Version 1.1**.
11
+
12
+ - Fira Code: Copyright 2014-2021 The Fira Code Project Authors
13
+ - Fira Sans: Digitized data copyright 2012-2016, The Mozilla Foundation and
14
+ Telefonica S.A.
15
+
16
+ - Fira Code: https://github.com/tonsky/FiraCode
17
+ - Fira Sans: https://github.com/mozilla/Fira
18
+
19
+ ## Notectl Math (bundled OpenType MATH font)
20
+
21
+ The formula plugin ships an opt-in OpenType MATH font, exported as
22
+ `NOTECTL_MATH_FONT` from `@notectl/core/fonts/math`. It is a **subset** of
23
+ **Noto Sans Math**, Copyright 2022 Google LLC, licensed under the
24
+ **SIL Open Font License, Version 1.1**.
25
+
26
+ Per the OFL's Reserved Font Name clause, this Modified Version does **not** use
27
+ the reserved name "Noto Sans Math"; its internal family name is "Notectl Math".
28
+
29
+ - Original font: Noto Sans Math — https://github.com/notofonts/math
30
+ - License: SIL Open Font License 1.1 — https://scripts.sil.org/OFL
31
+
32
+ ## SIL Open Font License, Version 1.1 - 26 February 2007
33
+
34
+ The following license applies to all bundled fonts listed above.
35
+
36
+ ```
37
+ Copyright 2014-2021 The Fira Code Project Authors (https://github.com/tonsky/FiraCode)
38
+ Digitized data copyright 2012-2016, The Mozilla Foundation and Telefonica S.A.
39
+ Copyright 2022 Google LLC.
40
+
41
+ This Font Software is licensed under the SIL Open Font License, Version 1.1.
42
+ This license is copied below, and is also available with a FAQ at:
43
+ https://scripts.sil.org/OFL
44
+
45
+ -----------------------------------------------------------
46
+ SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
47
+ -----------------------------------------------------------
48
+
49
+ PREAMBLE
50
+ The goals of the Open Font License (OFL) are to stimulate worldwide
51
+ development of collaborative font projects, to support the font creation
52
+ efforts of academic and linguistic communities, and to provide a free and
53
+ open framework in which fonts may be shared and improved in partnership
54
+ with others.
55
+
56
+ The OFL allows the licensed fonts to be used, studied, modified and
57
+ redistributed freely as long as they are not sold by themselves. The
58
+ fonts, including any derivative works, can be bundled, embedded,
59
+ redistributed and/or sold with any software provided that any reserved
60
+ names are not used by derivative works. The fonts and derivatives,
61
+ however, cannot be released under any other type of license. The
62
+ requirement for fonts to remain under this license does not apply to any
63
+ document created using the fonts or their derivatives.
64
+
65
+ DEFINITIONS
66
+ "Font Software" refers to the set of files released by the Copyright
67
+ Holder(s) under this license and clearly marked as such. This may include
68
+ source files, build scripts and documentation.
69
+
70
+ "Reserved Font Name" refers to any names specified as such after the
71
+ copyright statement(s).
72
+
73
+ "Original Version" refers to the collection of Font Software components as
74
+ distributed by the Copyright Holder(s).
75
+
76
+ "Modified Version" refers to any derivative made by adding to, deleting,
77
+ or substituting -- in part or in whole -- any of the components of the
78
+ Original Version, by changing formats or by porting the Font Software to a
79
+ new environment.
80
+
81
+ "Author" refers to any designer, engineer, programmer, technical writer or
82
+ other person who contributed to the Font Software.
83
+
84
+ PERMISSION & CONDITIONS
85
+ Permission is hereby granted, free of charge, to any person obtaining a
86
+ copy of the Font Software, to use, study, copy, merge, embed, modify,
87
+ redistribute, and sell modified and unmodified copies of the Font
88
+ Software, subject to the following conditions:
89
+
90
+ 1) Neither the Font Software nor any of its individual components, in
91
+ Original or Modified Versions, may be sold by itself.
92
+
93
+ 2) Original or Modified Versions of the Font Software may be bundled,
94
+ redistributed and/or sold with any software, provided that each copy
95
+ contains the above copyright notice and this license. These can be
96
+ included either as stand-alone text files, human-readable headers or in
97
+ the appropriate machine-readable metadata fields within text or binary
98
+ files as long as those fields can be easily viewed by the user.
99
+
100
+ 3) No Modified Version of the Font Software may use the Reserved Font
101
+ Name(s) unless explicit written permission is granted by the corresponding
102
+ Copyright Holder. This restriction only applies to the primary font name as
103
+ presented to the users.
104
+
105
+ 4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
106
+ Software shall not be used to promote, endorse or advertise any Modified
107
+ Version, except to acknowledge the contribution(s) of the Copyright
108
+ Holder(s) and the Author(s) or with their explicit written permission.
109
+
110
+ 5) The Font Software, modified or unmodified, in part or in whole, must be
111
+ distributed entirely under this license, and must not be distributed under
112
+ any other license. The requirement for fonts to remain under this license
113
+ does not apply to any document created using the Font Software.
114
+
115
+ TERMINATION
116
+ This license becomes null and void if any of the above conditions are not
117
+ met.
118
+
119
+ DISCLAIMER
120
+ THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
121
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
122
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
123
+ COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
124
+ COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
125
+ INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
126
+ DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
127
+ OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER DEALINGS
128
+ IN THE FONT SOFTWARE.
129
+ ```
@@ -1,2 +1,2 @@
1
- import{c as t}from"./StyleRuntime-BFKu52mS.mjs";import{a as e,c as s,n as i,o as n,r as a,t as l}from"./PluginHelpers-KDuTlmXm.mjs";import{t as o}from"./NodeSpecPatching-B_yLknTl.mjs";var r={alignStart:"Align Start",alignCenter:"Align Center",alignEnd:"Align End",justify:"Justify",toolbarLabel:"Alignment",toolbarTooltip:"Alignment"},g=/* #__PURE__ */Object.assign({"./locales/ar.ts":()=>import("./ar-Bdmunk5h.mjs"),"./locales/de.ts":()=>import("./de-B8-w9gPi.mjs"),"./locales/es.ts":()=>import("./es-B8K3Yvf3.mjs"),"./locales/fr.ts":()=>import("./fr-BeRlON1t.mjs"),"./locales/hi.ts":()=>import("./hi-Bl-yeeOI.mjs"),"./locales/pt.ts":()=>import("./pt-5VeuNDd2.mjs"),"./locales/ru.ts":()=>import("./ru-Yngw7nFP.mjs"),"./locales/zh.ts":()=>import("./zh-BvuAbM2S.mjs")});async function m(t){return s(g,t,r)}var c={alignments:["start","center","end","justify"],alignableTypes:["paragraph","heading","title","subtitle","table_cell","image"],defaults:{image:"center"}},h={start:'<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M15 15H3v2h12v-2zm0-8H3v2h12V7zM3 13h18v-2H3v2zm0 8h18v-2H3v2zM3 3v2h18V3H3z"/></svg>',center:'<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M7 15v2h10v-2H7zm-4 6h18v-2H3v2zm0-8h18v-2H3v2zm4-6v2h10V7H7zM3 3v2h18V3H3z"/></svg>',end:'<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M3 21h18v-2H3v2zm6-4h12v-2H9v2zm-6-4h18v-2H3v2zm6-4h12V7H9v2zM3 3v2h18V3H3z"/></svg>',justify:'<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M3 21h18v-2H3v2zm0-4h18v-2H3v2zm0-4h18v-2H3v2zm0-4h18V7H3v2zM3 3v2h18V3H3z"/></svg>'},p=class{id="alignment";name="Alignment";priority=90;config;locale;alignableTypes;constructor(t){this.config={...c,...t,defaults:{...c.defaults,...t?.defaults}}}async init(t){this.locale=await n(t,this.config.locale,r,m),this.alignableTypes=new Set(this.config.alignableTypes),this.patchNodeSpecs(t),this.registerCommands(t),this.registerKeymaps(t),this.registerToolbarItem(t),this.registerMiddleware(t)}patchNodeSpecs(t){o(t.getSchemaRegistry(),this.config.alignableTypes,{attrName:"align",getDefault:t=>this.config.defaults[t]??"start",applyToDOM:d})}registerCommands(t){for(const e of this.config.alignments)t.registerCommand(`align${l(e)}`,()=>this.setAlignment(t,e))}registerKeymaps(t){const e={};this.config.alignments.includes("start")&&(e["Mod-Shift-L"]=()=>t.executeCommand("alignStart")),this.config.alignments.includes("center")&&(e["Mod-Shift-E"]=()=>t.executeCommand("alignCenter")),this.config.alignments.includes("end")&&(e["Mod-Shift-R"]=()=>t.executeCommand("alignEnd")),this.config.alignments.includes("justify")&&(e["Mod-Shift-J"]=()=>t.executeCommand("alignJustify")),Object.keys(e).length>0&&t.registerKeymap(e)}registerToolbarItem(t){const e=this.config.alignments.map(t=>({label:this.getAlignmentLabel(t),command:`align${l(t)}`,icon:h[t]}));t.registerToolbarItem({id:"alignment",group:"block",icon:h.start,label:this.locale.toolbarLabel,tooltip:this.locale.toolbarTooltip,command:"alignStart",popupType:"dropdown",popupConfig:{items:e},isActive:t=>this.isNonDefaultAlignment(t),isEnabled:t=>this.isAlignable(t)})}getAlignmentLabel(t){return{start:this.locale.alignStart,center:this.locale.alignCenter,end:this.locale.alignEnd,justify:this.locale.justify}[t]}registerMiddleware(t){t.registerMiddleware((t,e,s)=>{let i=!1;const n=t.steps.map(t=>{if("setBlockType"!==t.type)return t;if(!this.alignableTypes.has(t.nodeType))return t;const e=t.previousAttrs?.align;return e&&"start"!==e?(i=!0,{...t,attrs:{...t.attrs,align:e}}):t});s(i?{...t,steps:n}:t)},{name:"alignment:preserve-align"})}setAlignment(t,s){const n=t.getState(),a=e(n);if(0===a.length)return!1;const l=n.transaction("command");let o=!1;for(const e of a){const t=n.getBlock(e);if(!t||!this.alignableTypes.has(t.type))continue;const i=n.getNodePath(e);i&&(l.setNodeAttr(i,{...t.attrs,align:s}),o=!0)}return!!o&&i(t,l.setSelection(n.selection).build())}isNonDefaultAlignment(t){const e=a(t);if(!e||!this.alignableTypes.has(e.type))return!1;const s=e.attrs?.align,i=this.config.defaults[e.type]??"start";return null!=s&&s!==i}isAlignable(t){const e=a(t);return null!=e&&this.alignableTypes.has(e.type)}};function d(e,s){const i=s.attrs?.align;"string"==typeof i&&"start"!==i&&t(e,"textAlign",i)}export{m as i,p as n,r,h as t};
2
- //# sourceMappingURL=AlignmentPlugin-DeD4C4EP.mjs.map
1
+ import{a as t,c as e,n as s,o as i,r as n,t as a}from"./PluginHelpers-KDuTlmXm.mjs";import{c as l}from"./StyleRuntime-DW6omotc.mjs";import{t as o}from"./NodeSpecPatching-B_yLknTl.mjs";var r={alignStart:"Align Start",alignCenter:"Align Center",alignEnd:"Align End",justify:"Justify",toolbarLabel:"Alignment",toolbarTooltip:"Alignment"},g=/* #__PURE__ */Object.assign({"./locales/ar.ts":()=>import("./ar-Bdmunk5h.mjs"),"./locales/de.ts":()=>import("./de-B8-w9gPi.mjs"),"./locales/es.ts":()=>import("./es-B8K3Yvf3.mjs"),"./locales/fr.ts":()=>import("./fr-BeRlON1t.mjs"),"./locales/hi.ts":()=>import("./hi-Bl-yeeOI.mjs"),"./locales/pt.ts":()=>import("./pt-5VeuNDd2.mjs"),"./locales/ru.ts":()=>import("./ru-Yngw7nFP.mjs"),"./locales/zh.ts":()=>import("./zh-BvuAbM2S.mjs")});async function m(t){return e(g,t,r)}var c={alignments:["start","center","end","justify"],alignableTypes:["paragraph","heading","title","subtitle","table_cell","image"],defaults:{image:"center"}},h={start:'<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M15 15H3v2h12v-2zm0-8H3v2h12V7zM3 13h18v-2H3v2zm0 8h18v-2H3v2zM3 3v2h18V3H3z"/></svg>',center:'<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M7 15v2h10v-2H7zm-4 6h18v-2H3v2zm0-8h18v-2H3v2zm4-6v2h10V7H7zM3 3v2h18V3H3z"/></svg>',end:'<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M3 21h18v-2H3v2zm6-4h12v-2H9v2zm-6-4h18v-2H3v2zm6-4h12V7H9v2zM3 3v2h18V3H3z"/></svg>',justify:'<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M3 21h18v-2H3v2zm0-4h18v-2H3v2zm0-4h18v-2H3v2zm0-4h18V7H3v2zM3 3v2h18V3H3z"/></svg>'},p=class{id="alignment";name="Alignment";priority=90;config;locale;alignableTypes;constructor(t){this.config={...c,...t,defaults:{...c.defaults,...t?.defaults}}}async init(t){this.locale=await i(t,this.config.locale,r,m),this.alignableTypes=new Set(this.config.alignableTypes),this.patchNodeSpecs(t),this.registerCommands(t),this.registerKeymaps(t),this.registerToolbarItem(t),this.registerMiddleware(t)}patchNodeSpecs(t){o(t.getSchemaRegistry(),this.config.alignableTypes,{attrName:"align",getDefault:t=>this.config.defaults[t]??"start",applyToDOM:d})}registerCommands(t){for(const e of this.config.alignments)t.registerCommand(`align${a(e)}`,()=>this.setAlignment(t,e))}registerKeymaps(t){const e={};this.config.alignments.includes("start")&&(e["Mod-Shift-L"]=()=>t.executeCommand("alignStart")),this.config.alignments.includes("center")&&(e["Mod-Shift-E"]=()=>t.executeCommand("alignCenter")),this.config.alignments.includes("end")&&(e["Mod-Shift-R"]=()=>t.executeCommand("alignEnd")),this.config.alignments.includes("justify")&&(e["Mod-Shift-J"]=()=>t.executeCommand("alignJustify")),Object.keys(e).length>0&&t.registerKeymap(e)}registerToolbarItem(t){const e=this.config.alignments.map(t=>({label:this.getAlignmentLabel(t),command:`align${a(t)}`,icon:h[t]}));t.registerToolbarItem({id:"alignment",group:"block",icon:h.start,label:this.locale.toolbarLabel,tooltip:this.locale.toolbarTooltip,command:"alignStart",popupType:"dropdown",popupConfig:{items:e},isActive:t=>this.isNonDefaultAlignment(t),isEnabled:t=>this.isAlignable(t)})}getAlignmentLabel(t){return{start:this.locale.alignStart,center:this.locale.alignCenter,end:this.locale.alignEnd,justify:this.locale.justify}[t]}registerMiddleware(t){t.registerMiddleware((t,e,s)=>{let i=!1;const n=t.steps.map(t=>{if("setBlockType"!==t.type)return t;if(!this.alignableTypes.has(t.nodeType))return t;const e=t.previousAttrs?.align;return e&&"start"!==e?(i=!0,{...t,attrs:{...t.attrs,align:e}}):t});s(i?{...t,steps:n}:t)},{name:"alignment:preserve-align"})}setAlignment(e,i){const n=e.getState(),a=t(n);if(0===a.length)return!1;const l=n.transaction("command");let o=!1;for(const t of a){const e=n.getBlock(t);if(!e||!this.alignableTypes.has(e.type))continue;const s=n.getNodePath(t);s&&(l.setNodeAttr(s,{...e.attrs,align:i}),o=!0)}return!!o&&s(e,l.setSelection(n.selection).build())}isNonDefaultAlignment(t){const e=n(t);if(!e||!this.alignableTypes.has(e.type))return!1;const s=e.attrs?.align,i=this.config.defaults[e.type]??"start";return null!=s&&s!==i}isAlignable(t){const e=n(t);return null!=e&&this.alignableTypes.has(e.type)}};function d(t,e){const s=e.attrs?.align;"string"==typeof s&&"start"!==s&&l(t,"textAlign",s)}export{m as i,p as n,r,h as t};
2
+ //# sourceMappingURL=AlignmentPlugin-C9Rr_R-g.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"AlignmentPlugin-DeD4C4EP.mjs","names":[],"sources":["../../src/plugins/alignment/AlignmentLocale.ts","../../src/plugins/alignment/AlignmentPlugin.ts"],"sourcesContent":["/** Locale interface and default English locale for the AlignmentPlugin. */\n\nimport { type LocaleModuleMap, loadLocaleModule } from '../shared/LocaleLoader.js';\n\nexport interface AlignmentLocale {\n\treadonly alignStart: string;\n\treadonly alignCenter: string;\n\treadonly alignEnd: string;\n\treadonly justify: string;\n\treadonly toolbarLabel: string;\n\treadonly toolbarTooltip: string;\n}\n\n// --- Default English Locale ---\n\nexport const ALIGNMENT_LOCALE_EN: AlignmentLocale = {\n\talignStart: 'Align Start',\n\talignCenter: 'Align Center',\n\talignEnd: 'Align End',\n\tjustify: 'Justify',\n\ttoolbarLabel: 'Alignment',\n\ttoolbarTooltip: 'Alignment',\n};\n\n// --- Lazy Locale Loader ---\n\nconst localeModules: LocaleModuleMap<AlignmentLocale> = import.meta.glob<{\n\tdefault: AlignmentLocale;\n}>('./locales/*.ts', { eager: false });\n\nexport async function loadAlignmentLocale(lang: string): Promise<AlignmentLocale> {\n\treturn loadLocaleModule(localeModules, lang, ALIGNMENT_LOCALE_EN);\n}\n","/**\n * AlignmentPlugin: adds start/center/end/justify alignment as a block\n * attribute on paragraphs, headings, images, and other alignable types.\n * Uses logical values (`start`/`end`) instead of physical (`left`/`right`)\n * for correct behavior with RTL text direction. Patches NodeSpecs to render\n * the `align` attribute via inline `text-align` style and provides toggle\n * commands, keyboard shortcuts, and a toolbar dropdown.\n */\n\nimport type { BlockAlignment } from '../../model/BlockAlignment.js';\nimport type { BlockNode } from '../../model/Document.js';\nimport type { BlockId } from '../../model/TypeBrands.js';\nimport type { EditorState } from '../../state/EditorState.js';\nimport { setStyleProperty } from '../../style/StyleRuntime.js';\nimport type { Plugin, PluginContext } from '../Plugin.js';\nimport { patchNodeSpecAttr } from '../shared/NodeSpecPatching.js';\nimport {\n\tcapitalize,\n\tdispatchIfPresent,\n\tgetSelectedBlock,\n\tgetSelectedBlockIds,\n\tresolveLocale,\n} from '../shared/PluginHelpers.js';\nimport {\n\tALIGNMENT_LOCALE_EN,\n\ttype AlignmentLocale,\n\tloadAlignmentLocale,\n} from './AlignmentLocale.js';\n\n// --- Public Types ---\n\nexport interface AlignmentConfig {\n\t/** Which alignments to expose. Defaults to all four. */\n\treadonly alignments: readonly BlockAlignment[];\n\t/** Block types that support alignment. Defaults to paragraph + heading + title + subtitle + table_cell + image. */\n\treadonly alignableTypes: readonly string[];\n\t/** Per-type default alignment (e.g. `{ image: 'center' }`). Falls back to `'start'`. */\n\treadonly defaults: Readonly<Record<string, BlockAlignment>>;\n\treadonly locale?: AlignmentLocale;\n}\n\n// --- Constants ---\n\nconst DEFAULT_CONFIG: AlignmentConfig = {\n\talignments: ['start', 'center', 'end', 'justify'],\n\talignableTypes: ['paragraph', 'heading', 'title', 'subtitle', 'table_cell', 'image'],\n\tdefaults: { image: 'center' },\n};\n\nexport const ALIGNMENT_ICONS: Readonly<Record<BlockAlignment, string>> = {\n\tstart:\n\t\t'<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\"><path d=\"M15 15H3v2h12v-2zm0-8H3v2h12V7zM3 13h18v-2H3v2zm0 8h18v-2H3v2zM3 3v2h18V3H3z\"/></svg>',\n\tcenter:\n\t\t'<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\"><path d=\"M7 15v2h10v-2H7zm-4 6h18v-2H3v2zm0-8h18v-2H3v2zm4-6v2h10V7H7zM3 3v2h18V3H3z\"/></svg>',\n\tend: '<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\"><path d=\"M3 21h18v-2H3v2zm6-4h12v-2H9v2zm-6-4h18v-2H3v2zm6-4h12V7H9v2zM3 3v2h18V3H3z\"/></svg>',\n\tjustify:\n\t\t'<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\"><path d=\"M3 21h18v-2H3v2zm0-4h18v-2H3v2zm0-4h18v-2H3v2zm0-4h18V7H3v2zM3 3v2h18V3H3z\"/></svg>',\n};\n\n// --- Plugin ---\n\nexport class AlignmentPlugin implements Plugin {\n\treadonly id = 'alignment';\n\treadonly name = 'Alignment';\n\treadonly priority = 90;\n\n\tprivate readonly config: AlignmentConfig;\n\tprivate locale!: AlignmentLocale;\n\tprivate alignableTypes!: ReadonlySet<string>;\n\n\tconstructor(config?: Partial<AlignmentConfig>) {\n\t\tthis.config = {\n\t\t\t...DEFAULT_CONFIG,\n\t\t\t...config,\n\t\t\tdefaults: { ...DEFAULT_CONFIG.defaults, ...config?.defaults },\n\t\t};\n\t}\n\n\tasync init(context: PluginContext): Promise<void> {\n\t\tthis.locale = await resolveLocale(\n\t\t\tcontext,\n\t\t\tthis.config.locale,\n\t\t\tALIGNMENT_LOCALE_EN,\n\t\t\tloadAlignmentLocale,\n\t\t);\n\n\t\tthis.alignableTypes = new Set(this.config.alignableTypes);\n\t\tthis.patchNodeSpecs(context);\n\t\tthis.registerCommands(context);\n\t\tthis.registerKeymaps(context);\n\t\tthis.registerToolbarItem(context);\n\t\tthis.registerMiddleware(context);\n\t}\n\n\t// --- NodeSpec Patching ---\n\n\t/**\n\t * Patches existing NodeSpecs for alignable block types to support the\n\t * `align` attribute and render it as an inline style. Skips types\n\t * that already define an `align` attribute in their spec.\n\t */\n\tprivate patchNodeSpecs(context: PluginContext): void {\n\t\tpatchNodeSpecAttr(context.getSchemaRegistry(), this.config.alignableTypes, {\n\t\t\tattrName: 'align',\n\t\t\tgetDefault: (type) => this.config.defaults[type] ?? 'start',\n\t\t\tapplyToDOM: applyAlignment,\n\t\t});\n\t}\n\n\t// --- Commands ---\n\n\tprivate registerCommands(context: PluginContext): void {\n\t\tfor (const alignment of this.config.alignments) {\n\t\t\tcontext.registerCommand(`align${capitalize(alignment)}`, () => {\n\t\t\t\treturn this.setAlignment(context, alignment);\n\t\t\t});\n\t\t}\n\t}\n\n\t// --- Keymaps ---\n\n\tprivate registerKeymaps(context: PluginContext): void {\n\t\tconst bindings: Record<string, () => boolean> = {};\n\n\t\tif (this.config.alignments.includes('start')) {\n\t\t\tbindings['Mod-Shift-L'] = () => context.executeCommand('alignStart');\n\t\t}\n\t\tif (this.config.alignments.includes('center')) {\n\t\t\tbindings['Mod-Shift-E'] = () => context.executeCommand('alignCenter');\n\t\t}\n\t\tif (this.config.alignments.includes('end')) {\n\t\t\tbindings['Mod-Shift-R'] = () => context.executeCommand('alignEnd');\n\t\t}\n\t\tif (this.config.alignments.includes('justify')) {\n\t\t\tbindings['Mod-Shift-J'] = () => context.executeCommand('alignJustify');\n\t\t}\n\n\t\tif (Object.keys(bindings).length > 0) {\n\t\t\tcontext.registerKeymap(bindings);\n\t\t}\n\t}\n\n\t// --- Toolbar ---\n\n\tprivate registerToolbarItem(context: PluginContext): void {\n\t\tconst dropdownItems = this.config.alignments.map((alignment) => ({\n\t\t\tlabel: this.getAlignmentLabel(alignment),\n\t\t\tcommand: `align${capitalize(alignment)}`,\n\t\t\ticon: ALIGNMENT_ICONS[alignment],\n\t\t}));\n\n\t\tcontext.registerToolbarItem({\n\t\t\tid: 'alignment',\n\t\t\tgroup: 'block',\n\t\t\ticon: ALIGNMENT_ICONS.start,\n\t\t\tlabel: this.locale.toolbarLabel,\n\t\t\ttooltip: this.locale.toolbarTooltip,\n\t\t\tcommand: 'alignStart',\n\t\t\tpopupType: 'dropdown',\n\t\t\tpopupConfig: { items: dropdownItems },\n\t\t\tisActive: (state) => this.isNonDefaultAlignment(state),\n\t\t\tisEnabled: (state) => this.isAlignable(state),\n\t\t});\n\t}\n\n\tprivate getAlignmentLabel(alignment: BlockAlignment): string {\n\t\tconst labels: Record<BlockAlignment, string> = {\n\t\t\tstart: this.locale.alignStart,\n\t\t\tcenter: this.locale.alignCenter,\n\t\t\tend: this.locale.alignEnd,\n\t\t\tjustify: this.locale.justify,\n\t\t};\n\t\treturn labels[alignment];\n\t}\n\n\t// --- Middleware ---\n\n\t/**\n\t * Preserves the `align` attribute when other plugins change the block\n\t * type (e.g. paragraph → heading) via `setBlockType`, which replaces attrs.\n\t */\n\tprivate registerMiddleware(context: PluginContext): void {\n\t\tcontext.registerMiddleware(\n\t\t\t(tr, _state, next) => {\n\t\t\t\tlet patched = false;\n\n\t\t\t\tconst patchedSteps = tr.steps.map((step) => {\n\t\t\t\t\tif (step.type !== 'setBlockType') return step;\n\t\t\t\t\tif (!this.alignableTypes.has(step.nodeType)) return step;\n\n\t\t\t\t\tconst prevAlign = step.previousAttrs?.align;\n\t\t\t\t\tif (!prevAlign || prevAlign === 'start') return step;\n\n\t\t\t\t\t// Carry forward align into new attrs\n\t\t\t\t\tpatched = true;\n\t\t\t\t\treturn {\n\t\t\t\t\t\t...step,\n\t\t\t\t\t\tattrs: { ...step.attrs, align: prevAlign },\n\t\t\t\t\t};\n\t\t\t\t});\n\n\t\t\t\tnext(patched ? { ...tr, steps: patchedSteps } : tr);\n\t\t\t},\n\t\t\t{ name: 'alignment:preserve-align' },\n\t\t);\n\t}\n\n\t// --- Alignment Logic ---\n\n\t/**\n\t * Applies `alignment` to every alignable block in the current selection in\n\t * a single transaction. A multi-block selection aligns all of its blocks,\n\t * not just the anchor; non-alignable blocks in the range are left untouched.\n\t */\n\tprivate setAlignment(context: PluginContext, alignment: BlockAlignment): boolean {\n\t\tconst state = context.getState();\n\t\tconst blockIds: BlockId[] = getSelectedBlockIds(state);\n\t\tif (blockIds.length === 0) return false;\n\n\t\tconst tb = state.transaction('command');\n\t\tlet changed = false;\n\n\t\tfor (const id of blockIds) {\n\t\t\tconst block = state.getBlock(id);\n\t\t\tif (!block || !this.alignableTypes.has(block.type)) continue;\n\n\t\t\tconst path = state.getNodePath(id);\n\t\t\tif (!path) continue;\n\n\t\t\ttb.setNodeAttr(path, { ...block.attrs, align: alignment });\n\t\t\tchanged = true;\n\t\t}\n\n\t\tif (!changed) return false;\n\n\t\treturn dispatchIfPresent(context, tb.setSelection(state.selection).build());\n\t}\n\n\tprivate isNonDefaultAlignment(state: EditorState): boolean {\n\t\tconst block = getSelectedBlock(state);\n\t\tif (!block || !this.alignableTypes.has(block.type)) return false;\n\t\tconst align = block.attrs?.align;\n\t\tconst defaultAlign: BlockAlignment = this.config.defaults[block.type] ?? 'start';\n\t\treturn align != null && align !== defaultAlign;\n\t}\n\n\tprivate isAlignable(state: EditorState): boolean {\n\t\tconst block = getSelectedBlock(state);\n\t\treturn block != null && this.alignableTypes.has(block.type);\n\t}\n}\n\n// --- Helpers ---\n\nfunction applyAlignment(el: HTMLElement, node: BlockNode): void {\n\tconst align = node.attrs?.align;\n\tif (typeof align === 'string' && align !== 'start') {\n\t\tsetStyleProperty(el, 'textAlign', align);\n\t}\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"AlignmentPlugin-C9Rr_R-g.mjs","names":[],"sources":["../../src/plugins/alignment/AlignmentLocale.ts","../../src/plugins/alignment/AlignmentPlugin.ts"],"sourcesContent":["/** Locale interface and default English locale for the AlignmentPlugin. */\n\nimport { type LocaleModuleMap, loadLocaleModule } from '../shared/LocaleLoader.js';\n\nexport interface AlignmentLocale {\n\treadonly alignStart: string;\n\treadonly alignCenter: string;\n\treadonly alignEnd: string;\n\treadonly justify: string;\n\treadonly toolbarLabel: string;\n\treadonly toolbarTooltip: string;\n}\n\n// --- Default English Locale ---\n\nexport const ALIGNMENT_LOCALE_EN: AlignmentLocale = {\n\talignStart: 'Align Start',\n\talignCenter: 'Align Center',\n\talignEnd: 'Align End',\n\tjustify: 'Justify',\n\ttoolbarLabel: 'Alignment',\n\ttoolbarTooltip: 'Alignment',\n};\n\n// --- Lazy Locale Loader ---\n\nconst localeModules: LocaleModuleMap<AlignmentLocale> = import.meta.glob<{\n\tdefault: AlignmentLocale;\n}>('./locales/*.ts', { eager: false });\n\nexport async function loadAlignmentLocale(lang: string): Promise<AlignmentLocale> {\n\treturn loadLocaleModule(localeModules, lang, ALIGNMENT_LOCALE_EN);\n}\n","/**\n * AlignmentPlugin: adds start/center/end/justify alignment as a block\n * attribute on paragraphs, headings, images, and other alignable types.\n * Uses logical values (`start`/`end`) instead of physical (`left`/`right`)\n * for correct behavior with RTL text direction. Patches NodeSpecs to render\n * the `align` attribute via inline `text-align` style and provides toggle\n * commands, keyboard shortcuts, and a toolbar dropdown.\n */\n\nimport type { BlockAlignment } from '../../model/BlockAlignment.js';\nimport type { BlockNode } from '../../model/Document.js';\nimport type { BlockId } from '../../model/TypeBrands.js';\nimport type { EditorState } from '../../state/EditorState.js';\nimport { setStyleProperty } from '../../style/StyleRuntime.js';\nimport type { Plugin, PluginContext } from '../Plugin.js';\nimport { patchNodeSpecAttr } from '../shared/NodeSpecPatching.js';\nimport {\n\tcapitalize,\n\tdispatchIfPresent,\n\tgetSelectedBlock,\n\tgetSelectedBlockIds,\n\tresolveLocale,\n} from '../shared/PluginHelpers.js';\nimport {\n\tALIGNMENT_LOCALE_EN,\n\ttype AlignmentLocale,\n\tloadAlignmentLocale,\n} from './AlignmentLocale.js';\n\n// --- Public Types ---\n\nexport interface AlignmentConfig {\n\t/** Which alignments to expose. Defaults to all four. */\n\treadonly alignments: readonly BlockAlignment[];\n\t/** Block types that support alignment. Defaults to paragraph + heading + title + subtitle + table_cell + image. */\n\treadonly alignableTypes: readonly string[];\n\t/** Per-type default alignment (e.g. `{ image: 'center' }`). Falls back to `'start'`. */\n\treadonly defaults: Readonly<Record<string, BlockAlignment>>;\n\treadonly locale?: AlignmentLocale;\n}\n\n// --- Constants ---\n\nconst DEFAULT_CONFIG: AlignmentConfig = {\n\talignments: ['start', 'center', 'end', 'justify'],\n\talignableTypes: ['paragraph', 'heading', 'title', 'subtitle', 'table_cell', 'image'],\n\tdefaults: { image: 'center' },\n};\n\nexport const ALIGNMENT_ICONS: Readonly<Record<BlockAlignment, string>> = {\n\tstart:\n\t\t'<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\"><path d=\"M15 15H3v2h12v-2zm0-8H3v2h12V7zM3 13h18v-2H3v2zm0 8h18v-2H3v2zM3 3v2h18V3H3z\"/></svg>',\n\tcenter:\n\t\t'<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\"><path d=\"M7 15v2h10v-2H7zm-4 6h18v-2H3v2zm0-8h18v-2H3v2zm4-6v2h10V7H7zM3 3v2h18V3H3z\"/></svg>',\n\tend: '<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\"><path d=\"M3 21h18v-2H3v2zm6-4h12v-2H9v2zm-6-4h18v-2H3v2zm6-4h12V7H9v2zM3 3v2h18V3H3z\"/></svg>',\n\tjustify:\n\t\t'<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\"><path d=\"M3 21h18v-2H3v2zm0-4h18v-2H3v2zm0-4h18v-2H3v2zm0-4h18V7H3v2zM3 3v2h18V3H3z\"/></svg>',\n};\n\n// --- Plugin ---\n\nexport class AlignmentPlugin implements Plugin {\n\treadonly id = 'alignment';\n\treadonly name = 'Alignment';\n\treadonly priority = 90;\n\n\tprivate readonly config: AlignmentConfig;\n\tprivate locale!: AlignmentLocale;\n\tprivate alignableTypes!: ReadonlySet<string>;\n\n\tconstructor(config?: Partial<AlignmentConfig>) {\n\t\tthis.config = {\n\t\t\t...DEFAULT_CONFIG,\n\t\t\t...config,\n\t\t\tdefaults: { ...DEFAULT_CONFIG.defaults, ...config?.defaults },\n\t\t};\n\t}\n\n\tasync init(context: PluginContext): Promise<void> {\n\t\tthis.locale = await resolveLocale(\n\t\t\tcontext,\n\t\t\tthis.config.locale,\n\t\t\tALIGNMENT_LOCALE_EN,\n\t\t\tloadAlignmentLocale,\n\t\t);\n\n\t\tthis.alignableTypes = new Set(this.config.alignableTypes);\n\t\tthis.patchNodeSpecs(context);\n\t\tthis.registerCommands(context);\n\t\tthis.registerKeymaps(context);\n\t\tthis.registerToolbarItem(context);\n\t\tthis.registerMiddleware(context);\n\t}\n\n\t// --- NodeSpec Patching ---\n\n\t/**\n\t * Patches existing NodeSpecs for alignable block types to support the\n\t * `align` attribute and render it as an inline style. Skips types\n\t * that already define an `align` attribute in their spec.\n\t */\n\tprivate patchNodeSpecs(context: PluginContext): void {\n\t\tpatchNodeSpecAttr(context.getSchemaRegistry(), this.config.alignableTypes, {\n\t\t\tattrName: 'align',\n\t\t\tgetDefault: (type) => this.config.defaults[type] ?? 'start',\n\t\t\tapplyToDOM: applyAlignment,\n\t\t});\n\t}\n\n\t// --- Commands ---\n\n\tprivate registerCommands(context: PluginContext): void {\n\t\tfor (const alignment of this.config.alignments) {\n\t\t\tcontext.registerCommand(`align${capitalize(alignment)}`, () => {\n\t\t\t\treturn this.setAlignment(context, alignment);\n\t\t\t});\n\t\t}\n\t}\n\n\t// --- Keymaps ---\n\n\tprivate registerKeymaps(context: PluginContext): void {\n\t\tconst bindings: Record<string, () => boolean> = {};\n\n\t\tif (this.config.alignments.includes('start')) {\n\t\t\tbindings['Mod-Shift-L'] = () => context.executeCommand('alignStart');\n\t\t}\n\t\tif (this.config.alignments.includes('center')) {\n\t\t\tbindings['Mod-Shift-E'] = () => context.executeCommand('alignCenter');\n\t\t}\n\t\tif (this.config.alignments.includes('end')) {\n\t\t\tbindings['Mod-Shift-R'] = () => context.executeCommand('alignEnd');\n\t\t}\n\t\tif (this.config.alignments.includes('justify')) {\n\t\t\tbindings['Mod-Shift-J'] = () => context.executeCommand('alignJustify');\n\t\t}\n\n\t\tif (Object.keys(bindings).length > 0) {\n\t\t\tcontext.registerKeymap(bindings);\n\t\t}\n\t}\n\n\t// --- Toolbar ---\n\n\tprivate registerToolbarItem(context: PluginContext): void {\n\t\tconst dropdownItems = this.config.alignments.map((alignment) => ({\n\t\t\tlabel: this.getAlignmentLabel(alignment),\n\t\t\tcommand: `align${capitalize(alignment)}`,\n\t\t\ticon: ALIGNMENT_ICONS[alignment],\n\t\t}));\n\n\t\tcontext.registerToolbarItem({\n\t\t\tid: 'alignment',\n\t\t\tgroup: 'block',\n\t\t\ticon: ALIGNMENT_ICONS.start,\n\t\t\tlabel: this.locale.toolbarLabel,\n\t\t\ttooltip: this.locale.toolbarTooltip,\n\t\t\tcommand: 'alignStart',\n\t\t\tpopupType: 'dropdown',\n\t\t\tpopupConfig: { items: dropdownItems },\n\t\t\tisActive: (state) => this.isNonDefaultAlignment(state),\n\t\t\tisEnabled: (state) => this.isAlignable(state),\n\t\t});\n\t}\n\n\tprivate getAlignmentLabel(alignment: BlockAlignment): string {\n\t\tconst labels: Record<BlockAlignment, string> = {\n\t\t\tstart: this.locale.alignStart,\n\t\t\tcenter: this.locale.alignCenter,\n\t\t\tend: this.locale.alignEnd,\n\t\t\tjustify: this.locale.justify,\n\t\t};\n\t\treturn labels[alignment];\n\t}\n\n\t// --- Middleware ---\n\n\t/**\n\t * Preserves the `align` attribute when other plugins change the block\n\t * type (e.g. paragraph → heading) via `setBlockType`, which replaces attrs.\n\t */\n\tprivate registerMiddleware(context: PluginContext): void {\n\t\tcontext.registerMiddleware(\n\t\t\t(tr, _state, next) => {\n\t\t\t\tlet patched = false;\n\n\t\t\t\tconst patchedSteps = tr.steps.map((step) => {\n\t\t\t\t\tif (step.type !== 'setBlockType') return step;\n\t\t\t\t\tif (!this.alignableTypes.has(step.nodeType)) return step;\n\n\t\t\t\t\tconst prevAlign = step.previousAttrs?.align;\n\t\t\t\t\tif (!prevAlign || prevAlign === 'start') return step;\n\n\t\t\t\t\t// Carry forward align into new attrs\n\t\t\t\t\tpatched = true;\n\t\t\t\t\treturn {\n\t\t\t\t\t\t...step,\n\t\t\t\t\t\tattrs: { ...step.attrs, align: prevAlign },\n\t\t\t\t\t};\n\t\t\t\t});\n\n\t\t\t\tnext(patched ? { ...tr, steps: patchedSteps } : tr);\n\t\t\t},\n\t\t\t{ name: 'alignment:preserve-align' },\n\t\t);\n\t}\n\n\t// --- Alignment Logic ---\n\n\t/**\n\t * Applies `alignment` to every alignable block in the current selection in\n\t * a single transaction. A multi-block selection aligns all of its blocks,\n\t * not just the anchor; non-alignable blocks in the range are left untouched.\n\t */\n\tprivate setAlignment(context: PluginContext, alignment: BlockAlignment): boolean {\n\t\tconst state = context.getState();\n\t\tconst blockIds: BlockId[] = getSelectedBlockIds(state);\n\t\tif (blockIds.length === 0) return false;\n\n\t\tconst tb = state.transaction('command');\n\t\tlet changed = false;\n\n\t\tfor (const id of blockIds) {\n\t\t\tconst block = state.getBlock(id);\n\t\t\tif (!block || !this.alignableTypes.has(block.type)) continue;\n\n\t\t\tconst path = state.getNodePath(id);\n\t\t\tif (!path) continue;\n\n\t\t\ttb.setNodeAttr(path, { ...block.attrs, align: alignment });\n\t\t\tchanged = true;\n\t\t}\n\n\t\tif (!changed) return false;\n\n\t\treturn dispatchIfPresent(context, tb.setSelection(state.selection).build());\n\t}\n\n\tprivate isNonDefaultAlignment(state: EditorState): boolean {\n\t\tconst block = getSelectedBlock(state);\n\t\tif (!block || !this.alignableTypes.has(block.type)) return false;\n\t\tconst align = block.attrs?.align;\n\t\tconst defaultAlign: BlockAlignment = this.config.defaults[block.type] ?? 'start';\n\t\treturn align != null && align !== defaultAlign;\n\t}\n\n\tprivate isAlignable(state: EditorState): boolean {\n\t\tconst block = getSelectedBlock(state);\n\t\treturn block != null && this.alignableTypes.has(block.type);\n\t}\n}\n\n// --- Helpers ---\n\nfunction applyAlignment(el: HTMLElement, node: BlockNode): void {\n\tconst align = node.attrs?.align;\n\tif (typeof align === 'string' && align !== 'start') {\n\t\tsetStyleProperty(el, 'textAlign', align);\n\t}\n}\n"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- import{C as n}from"./Document-r7vLOAGA.mjs";function t(n,t){return n.type===t}function r(n,t){return n.type===t}function e(t,r){return n(t)&&t.inlineType===r}export{r as n,t as r,e as t};
2
- //# sourceMappingURL=AttrRegistry-DcDVyzLm.mjs.map
1
+ import{T as n}from"./Document-827l3P80.mjs";function t(n,t){return n.type===t}function r(n,t){return n.type===t}function e(t,r){return n(t)&&t.inlineType===r}export{r as n,t as r,e as t};
2
+ //# sourceMappingURL=AttrRegistry-B3zB02z9.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AttrRegistry-B3zB02z9.mjs","names":[],"sources":["../../src/model/AttrRegistry.ts"],"sourcesContent":["/**\n * Module-augmentable attribute registries for type-safe node/mark attributes.\n *\n * Plugins extend these interfaces via `declare module`:\n * @example\n * declare module '../../model/AttrRegistry.js' {\n * interface NodeAttrRegistry {\n * heading: { level: HeadingLevel; align?: BlockAlignment };\n * }\n * }\n */\n\nimport type { BlockAlignment } from './BlockAlignment.js';\nimport type { BlockAttrs, BlockNode, InlineNode, Mark } from './Document.js';\nimport { isInlineNode } from './Document.js';\n\n/** Plugins augment this interface to register typed node attributes. */\nexport interface NodeAttrRegistry {\n\tparagraph: { align?: BlockAlignment };\n}\n\n/** Plugins augment this interface to register typed mark attributes. */\nexport interface MarkAttrRegistry {\n\tbold: Record<string, never>;\n\titalic: Record<string, never>;\n\tunderline: Record<string, never>;\n}\n\n/** Resolves typed attributes for known node types, falls back for unknown. */\nexport type NodeAttrsFor<T extends string> = T extends keyof NodeAttrRegistry\n\t? NodeAttrRegistry[T]\n\t: BlockAttrs;\n\n/** Resolves typed attributes for known mark types, falls back for unknown. */\nexport type MarkAttrsFor<T extends string> = T extends keyof MarkAttrRegistry\n\t? MarkAttrRegistry[T]\n\t: Record<string, string | number | boolean>;\n\n/** Narrows a BlockNode to a typed variant with known attributes. */\nexport function isNodeOfType<T extends keyof NodeAttrRegistry>(\n\tnode: BlockNode,\n\ttype: T,\n): node is BlockNode & { readonly type: T; readonly attrs: NodeAttrRegistry[T] } {\n\treturn (node.type as string) === type;\n}\n\n/** Narrows a Mark to a typed variant with known attributes. */\nexport function isMarkOfType<T extends keyof MarkAttrRegistry>(\n\tmark: Mark,\n\ttype: T,\n): mark is Mark & { readonly type: T; readonly attrs: MarkAttrRegistry[T] } {\n\treturn (mark.type as string) === type;\n}\n\n// --- InlineNode Attribute Registry ---\n\n/** Plugins augment this interface to register typed inline node attributes. */\n// biome-ignore lint/suspicious/noEmptyInterface: module augmentation requires interface\nexport interface InlineNodeAttrRegistry {}\n\n/** Resolves typed attributes for known inline node types, falls back for unknown. */\nexport type InlineNodeAttrsFor<T extends string> = T extends keyof InlineNodeAttrRegistry\n\t? InlineNodeAttrRegistry[T]\n\t: Record<string, string | number | boolean>;\n\n/** Narrows an InlineNode to a typed variant with known attributes. */\nexport function isInlineNodeOfType<T extends keyof InlineNodeAttrRegistry>(\n\tnode: InlineNode,\n\tinlineNodeType: T,\n): node is InlineNode & {\n\treadonly inlineType: T;\n\treadonly attrs: InlineNodeAttrRegistry[T];\n} {\n\treturn isInlineNode(node) && (node.inlineType as string) === inlineNodeType;\n}\n"],"mappings":"4CAuCA,SAAgB,EACf,EACA,GAEA,OAAQ,EAAK,OAAoB,CAClC,CAGA,SAAgB,EACf,EACA,GAEA,OAAQ,EAAK,OAAoB,CAClC,CAcA,SAAgB,EACf,EACA,GAKA,OAAO,EAAa,IAAU,EAAK,aAA0B,CAC9D"}
@@ -0,0 +1,2 @@
1
+ import{D as t,S as n,b as o,g as e,y as r}from"./Document-827l3P80.mjs";import{d as s,o as c,u as i}from"./Selection-HYoVFpAx.mjs";import{i as a}from"./TypeBrands-Ch9856Gb.mjs";import{n as l}from"./RangeIterator-DP7Ud3Gp.mjs";import{n as u}from"./AttrRegistry-B3zB02z9.mjs";function f(t,n){return!1!==t.getMarkSpec?.(n)?.inclusive}function m(t){if(t.storedMarks)return t.storedMarks;const n=t.selection;if(!i(n)||!c(n))return[];const o=t.getBlock(n.anchor.blockId);return o?r(o,n.anchor.offset,n=>f(t.schema,n)):[]}function d(t,n){const o=t.selection;if(!i(o))return null;const e=a(n.type);if(c(o)){if(!t.getBlock(o.anchor.blockId))return null;const r=[...m(t).filter(t=>t.type!==e),n];return t.transaction("command").setStoredMarks(r,t.storedMarks).setSelection(o).build()}const r=s(o,t.getBlockOrder()),u=t.transaction("command");return l(t,r,(o,r,s)=>{const c=t.getBlock(o);if(c){const t=M(c,e,r,s);t&&u.removeMark(o,r,s,t)}u.addMark(o,r,s,n)}),u.setSelection(o),u.build()}function k(t,o){const e=t.selection;if(!i(e))return null;if(c(e)){if(!t.getBlock(e.anchor.blockId))return null;const r=m(t);if(!n(r,o))return null;const s=r.filter(t=>t.type!==o);return t.transaction("command").setStoredMarks(s,t.storedMarks).setSelection(e).build()}const r=s(e,t.getBlockOrder()),a=t.transaction("command");return l(t,r,(n,e,r)=>{const s=t.getBlock(n),c=s?M(s,o,e,r):void 0;a.removeMark(n,e,r,c??{type:o})}),a.setSelection(e),a.build()}function p(t,n,o){const r=t.selection;if(!i(r))return null;let s;if(c(r))s=m(t);else{const n=t.getBlock(r.anchor.blockId);if(!n)return null;s=e(n,r.anchor.offset)}const a=s.find(t=>t.type===n);return a&&u(a,n)?o(a):null}function g(t,n){return null!==p(t,n,()=>!0)}function M(n,e,r,s){const c=o(n);let i=0;for(const o of c){if(!t(o)){i+=1;continue}const n=i+o.text.length;if(n>r&&i<s){const t=o.marks.find(t=>t.type===e);if(t)return t}i=n}}export{f as a,k as i,p as n,m as o,g as r,d as t};
2
+ //# sourceMappingURL=AttributedMarkCommands-BCvmqeFZ.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"AttributedMarkCommands-D4W2Jgpj.mjs","names":[],"sources":["../../src/commands/CursorMarks.ts","../../src/commands/AttributedMarkCommands.ts"],"sourcesContent":["/**\n * Resolves the marks active at a collapsed cursor for insertion and toolbar\n * state. Centralizes the `storedMarks ?? derived-marks` lookup that several\n * command modules previously duplicated, and makes that derivation honor\n * mark inclusivity (see {@link MarkSpec.inclusive}) so non-inclusive marks\n * such as links do not bleed onto text typed at their right boundary.\n */\n\nimport type { Mark } from '../model/Document.js';\nimport { getCursorMarks } from '../model/Document.js';\nimport type { Schema } from '../model/Schema.js';\nimport { isCollapsed, isTextSelection } from '../model/Selection.js';\nimport type { MarkTypeName } from '../model/TypeBrands.js';\nimport type { EditorState } from '../state/EditorState.js';\n\n/** A mark extends onto adjacent typing unless its spec opts out via `inclusive: false`. */\nexport function isMarkInclusive(schema: Schema, type: MarkTypeName): boolean {\n\treturn schema.getMarkSpec?.(type)?.inclusive !== false;\n}\n\n/**\n * Returns the marks a collapsed cursor carries: stored marks when present,\n * otherwise the inclusivity-aware marks derived from the surrounding content.\n * Returns an empty set for non-text or non-collapsed selections.\n */\nexport function resolveCursorMarks(state: EditorState): readonly Mark[] {\n\tif (state.storedMarks) return state.storedMarks;\n\n\tconst sel = state.selection;\n\tif (!isTextSelection(sel) || !isCollapsed(sel)) return [];\n\n\tconst block = state.getBlock(sel.anchor.blockId);\n\tif (!block) return [];\n\n\treturn getCursorMarks(block, sel.anchor.offset, (type) => isMarkInclusive(state.schema, type));\n}\n","/**\n * Generic helpers for attributed marks (marks with key/value attrs).\n *\n * Unlike boolean marks (`bold`, `italic`) that toggle on/off, attributed\n * marks (`font`, `fontSize`, `textColor`, `highlight`) carry data and use\n * **replace** semantics: applying a new value removes the old one first.\n *\n * These helpers extract the duplicated collapsed-vs-range branching that\n * was previously copy-pasted across ColorMarkOperations, FontSizeOperations,\n * and FontPlugin.\n */\n\nimport { isMarkOfType } from '../model/AttrRegistry.js';\nimport type { MarkAttrRegistry } from '../model/AttrRegistry.js';\nimport type { BlockNode, Mark, TextNode } from '../model/Document.js';\nimport {\n\tgetBlockMarksAtOffset,\n\tgetInlineChildren,\n\thasMark,\n\tisTextNode,\n} from '../model/Document.js';\nimport type { InlineNode } from '../model/Document.js';\nimport { isCollapsed, isTextSelection, selectionRange } from '../model/Selection.js';\nimport { markType } from '../model/TypeBrands.js';\nimport type { MarkTypeName } from '../model/TypeBrands.js';\nimport type { EditorState } from '../state/EditorState.js';\nimport type { Transaction } from '../state/Transaction.js';\nimport { resolveCursorMarks } from './CursorMarks.js';\nimport { forEachBlockInRange } from './RangeIterator.js';\n\n/**\n * Applies an attributed mark to the current selection.\n *\n * - **Collapsed cursor**: replaces stored marks (filters out old mark of the\n * same type, appends the new one).\n * - **Range selection**: removes then re-adds the mark in every block span.\n *\n * Returns the built `Transaction`, or `null` when the selection is\n * unsupported (node-selection / gap-cursor) or the anchor block is missing.\n */\nexport function applyAttributedMark(state: EditorState, mark: Mark): Transaction | null {\n\tconst sel = state.selection;\n\tif (!isTextSelection(sel)) return null;\n\n\tconst typeName: MarkTypeName = markType(mark.type as string);\n\n\tif (isCollapsed(sel)) {\n\t\tconst anchorBlock = state.getBlock(sel.anchor.blockId);\n\t\tif (!anchorBlock) return null;\n\t\tconst currentMarks: readonly Mark[] = resolveCursorMarks(state);\n\t\tconst withoutMark: readonly Mark[] = currentMarks.filter((m) => m.type !== typeName);\n\t\tconst newMarks: readonly Mark[] = [...withoutMark, mark];\n\n\t\treturn state\n\t\t\t.transaction('command')\n\t\t\t.setStoredMarks(newMarks, state.storedMarks)\n\t\t\t.setSelection(sel)\n\t\t\t.build();\n\t}\n\n\tconst range = selectionRange(sel, state.getBlockOrder());\n\tconst builder = state.transaction('command');\n\n\tforEachBlockInRange(state, range, (blockId, from, to) => {\n\t\tconst block: BlockNode | undefined = state.getBlock(blockId);\n\t\tif (block) {\n\t\t\tconst existing: Mark | undefined = findMarkInRange(block, typeName, from, to);\n\t\t\tif (existing) {\n\t\t\t\tbuilder.removeMark(blockId, from, to, existing);\n\t\t\t}\n\t\t}\n\t\tbuilder.addMark(blockId, from, to, mark);\n\t});\n\n\tbuilder.setSelection(sel);\n\treturn builder.build();\n}\n\n/**\n * Removes an attributed mark from the current selection.\n *\n * - **Collapsed cursor**: filters the mark out of stored marks.\n * Returns `null` when the mark was not present.\n * - **Range selection**: removes the mark across all block spans.\n *\n * Returns the built `Transaction`, or `null` when the selection is\n * unsupported or the mark is absent at a collapsed cursor.\n */\nexport function removeAttributedMark(\n\tstate: EditorState,\n\tmarkTypeName: MarkTypeName,\n): Transaction | null {\n\tconst sel = state.selection;\n\tif (!isTextSelection(sel)) return null;\n\n\tif (isCollapsed(sel)) {\n\t\tconst anchorBlock = state.getBlock(sel.anchor.blockId);\n\t\tif (!anchorBlock) return null;\n\t\tconst currentMarks: readonly Mark[] = resolveCursorMarks(state);\n\t\tif (!hasMark(currentMarks, markTypeName)) return null;\n\n\t\tconst newMarks: readonly Mark[] = currentMarks.filter((m) => m.type !== markTypeName);\n\t\treturn state\n\t\t\t.transaction('command')\n\t\t\t.setStoredMarks(newMarks, state.storedMarks)\n\t\t\t.setSelection(sel)\n\t\t\t.build();\n\t}\n\n\tconst range = selectionRange(sel, state.getBlockOrder());\n\tconst builder = state.transaction('command');\n\n\tforEachBlockInRange(state, range, (blockId, from, to) => {\n\t\tconst block: BlockNode | undefined = state.getBlock(blockId);\n\t\tconst existing: Mark | undefined = block\n\t\t\t? findMarkInRange(block, markTypeName, from, to)\n\t\t\t: undefined;\n\t\tbuilder.removeMark(blockId, from, to, existing ?? { type: markTypeName });\n\t});\n\n\tbuilder.setSelection(sel);\n\treturn builder.build();\n}\n\n/**\n * Extracts a typed attribute value from the mark at the current selection.\n *\n * Looks at stored marks (collapsed w/ stored), block marks at cursor offset\n * (collapsed w/o stored), or anchor-block marks (range).\n *\n * @param extractFn — Narrows the found mark and returns the desired value,\n * or `null` when the mark's attrs don't match expectations.\n */\nexport function getMarkAttrAtSelection<K extends keyof MarkAttrRegistry, V>(\n\tstate: EditorState,\n\tmarkTypeName: K,\n\textractFn: (mark: Mark & { readonly type: K; readonly attrs: MarkAttrRegistry[K] }) => V | null,\n): V | null {\n\tconst sel = state.selection;\n\tif (!isTextSelection(sel)) return null;\n\n\t// Collapsed cursor honors stored marks and right-boundary inclusivity; a\n\t// range reads the raw content marks at its anchor.\n\tlet marks: readonly Mark[];\n\tif (isCollapsed(sel)) {\n\t\tmarks = resolveCursorMarks(state);\n\t} else {\n\t\tconst block = state.getBlock(sel.anchor.blockId);\n\t\tif (!block) return null;\n\t\tmarks = getBlockMarksAtOffset(block, sel.anchor.offset);\n\t}\n\n\tconst found = marks.find((m) => (m.type as string) === markTypeName);\n\treturn found && isMarkOfType(found, markTypeName) ? extractFn(found) : null;\n}\n\n/**\n * Returns `true` when the given attributed mark type is present at the\n * current selection (collapsed or range).\n */\nexport function isAttributedMarkActive<K extends keyof MarkAttrRegistry>(\n\tstate: EditorState,\n\tmarkTypeName: K,\n): boolean {\n\treturn getMarkAttrAtSelection(state, markTypeName, () => true as const) !== null;\n}\n\n/**\n * Finds the first mark of the given type within an offset range of a block.\n *\n * Returns the full mark (including attrs) so callers can pass it to\n * `removeMark` for correct undo inversion, or `undefined` when absent.\n */\nfunction findMarkInRange(\n\tblock: BlockNode,\n\ttypeName: MarkTypeName,\n\tfrom: number,\n\tto: number,\n): Mark | undefined {\n\tconst children: readonly (TextNode | InlineNode)[] = getInlineChildren(block);\n\tlet pos = 0;\n\n\tfor (const child of children) {\n\t\tif (!isTextNode(child)) {\n\t\t\tpos += 1;\n\t\t\tcontinue;\n\t\t}\n\t\tconst nodeEnd: number = pos + child.text.length;\n\t\tif (nodeEnd > from && pos < to) {\n\t\t\tconst found: Mark | undefined = child.marks.find((m) => m.type === typeName);\n\t\t\tif (found) return found;\n\t\t}\n\t\tpos = nodeEnd;\n\t}\n\treturn undefined;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"AttributedMarkCommands-BCvmqeFZ.mjs","names":[],"sources":["../../src/commands/CursorMarks.ts","../../src/commands/AttributedMarkCommands.ts"],"sourcesContent":["/**\n * Resolves the marks active at a collapsed cursor for insertion and toolbar\n * state. Centralizes the `storedMarks ?? derived-marks` lookup that several\n * command modules previously duplicated, and makes that derivation honor\n * mark inclusivity (see {@link MarkSpec.inclusive}) so non-inclusive marks\n * such as links do not bleed onto text typed at their right boundary.\n */\n\nimport type { Mark } from '../model/Document.js';\nimport { getCursorMarks } from '../model/Document.js';\nimport type { Schema } from '../model/Schema.js';\nimport { isCollapsed, isTextSelection } from '../model/Selection.js';\nimport type { MarkTypeName } from '../model/TypeBrands.js';\nimport type { EditorState } from '../state/EditorState.js';\n\n/** A mark extends onto adjacent typing unless its spec opts out via `inclusive: false`. */\nexport function isMarkInclusive(schema: Schema, type: MarkTypeName): boolean {\n\treturn schema.getMarkSpec?.(type)?.inclusive !== false;\n}\n\n/**\n * Returns the marks a collapsed cursor carries: stored marks when present,\n * otherwise the inclusivity-aware marks derived from the surrounding content.\n * Returns an empty set for non-text or non-collapsed selections.\n */\nexport function resolveCursorMarks(state: EditorState): readonly Mark[] {\n\tif (state.storedMarks) return state.storedMarks;\n\n\tconst sel = state.selection;\n\tif (!isTextSelection(sel) || !isCollapsed(sel)) return [];\n\n\tconst block = state.getBlock(sel.anchor.blockId);\n\tif (!block) return [];\n\n\treturn getCursorMarks(block, sel.anchor.offset, (type) => isMarkInclusive(state.schema, type));\n}\n","/**\n * Generic helpers for attributed marks (marks with key/value attrs).\n *\n * Unlike boolean marks (`bold`, `italic`) that toggle on/off, attributed\n * marks (`font`, `fontSize`, `textColor`, `highlight`) carry data and use\n * **replace** semantics: applying a new value removes the old one first.\n *\n * These helpers extract the duplicated collapsed-vs-range branching that\n * was previously copy-pasted across ColorMarkOperations, FontSizeOperations,\n * and FontPlugin.\n */\n\nimport { isMarkOfType } from '../model/AttrRegistry.js';\nimport type { MarkAttrRegistry } from '../model/AttrRegistry.js';\nimport type { BlockNode, Mark, TextNode } from '../model/Document.js';\nimport {\n\tgetBlockMarksAtOffset,\n\tgetInlineChildren,\n\thasMark,\n\tisTextNode,\n} from '../model/Document.js';\nimport type { InlineNode } from '../model/Document.js';\nimport { isCollapsed, isTextSelection, selectionRange } from '../model/Selection.js';\nimport { markType } from '../model/TypeBrands.js';\nimport type { MarkTypeName } from '../model/TypeBrands.js';\nimport type { EditorState } from '../state/EditorState.js';\nimport type { Transaction } from '../state/Transaction.js';\nimport { resolveCursorMarks } from './CursorMarks.js';\nimport { forEachBlockInRange } from './RangeIterator.js';\n\n/**\n * Applies an attributed mark to the current selection.\n *\n * - **Collapsed cursor**: replaces stored marks (filters out old mark of the\n * same type, appends the new one).\n * - **Range selection**: removes then re-adds the mark in every block span.\n *\n * Returns the built `Transaction`, or `null` when the selection is\n * unsupported (node-selection / gap-cursor) or the anchor block is missing.\n */\nexport function applyAttributedMark(state: EditorState, mark: Mark): Transaction | null {\n\tconst sel = state.selection;\n\tif (!isTextSelection(sel)) return null;\n\n\tconst typeName: MarkTypeName = markType(mark.type as string);\n\n\tif (isCollapsed(sel)) {\n\t\tconst anchorBlock = state.getBlock(sel.anchor.blockId);\n\t\tif (!anchorBlock) return null;\n\t\tconst currentMarks: readonly Mark[] = resolveCursorMarks(state);\n\t\tconst withoutMark: readonly Mark[] = currentMarks.filter((m) => m.type !== typeName);\n\t\tconst newMarks: readonly Mark[] = [...withoutMark, mark];\n\n\t\treturn state\n\t\t\t.transaction('command')\n\t\t\t.setStoredMarks(newMarks, state.storedMarks)\n\t\t\t.setSelection(sel)\n\t\t\t.build();\n\t}\n\n\tconst range = selectionRange(sel, state.getBlockOrder());\n\tconst builder = state.transaction('command');\n\n\tforEachBlockInRange(state, range, (blockId, from, to) => {\n\t\tconst block: BlockNode | undefined = state.getBlock(blockId);\n\t\tif (block) {\n\t\t\tconst existing: Mark | undefined = findMarkInRange(block, typeName, from, to);\n\t\t\tif (existing) {\n\t\t\t\tbuilder.removeMark(blockId, from, to, existing);\n\t\t\t}\n\t\t}\n\t\tbuilder.addMark(blockId, from, to, mark);\n\t});\n\n\tbuilder.setSelection(sel);\n\treturn builder.build();\n}\n\n/**\n * Removes an attributed mark from the current selection.\n *\n * - **Collapsed cursor**: filters the mark out of stored marks.\n * Returns `null` when the mark was not present.\n * - **Range selection**: removes the mark across all block spans.\n *\n * Returns the built `Transaction`, or `null` when the selection is\n * unsupported or the mark is absent at a collapsed cursor.\n */\nexport function removeAttributedMark(\n\tstate: EditorState,\n\tmarkTypeName: MarkTypeName,\n): Transaction | null {\n\tconst sel = state.selection;\n\tif (!isTextSelection(sel)) return null;\n\n\tif (isCollapsed(sel)) {\n\t\tconst anchorBlock = state.getBlock(sel.anchor.blockId);\n\t\tif (!anchorBlock) return null;\n\t\tconst currentMarks: readonly Mark[] = resolveCursorMarks(state);\n\t\tif (!hasMark(currentMarks, markTypeName)) return null;\n\n\t\tconst newMarks: readonly Mark[] = currentMarks.filter((m) => m.type !== markTypeName);\n\t\treturn state\n\t\t\t.transaction('command')\n\t\t\t.setStoredMarks(newMarks, state.storedMarks)\n\t\t\t.setSelection(sel)\n\t\t\t.build();\n\t}\n\n\tconst range = selectionRange(sel, state.getBlockOrder());\n\tconst builder = state.transaction('command');\n\n\tforEachBlockInRange(state, range, (blockId, from, to) => {\n\t\tconst block: BlockNode | undefined = state.getBlock(blockId);\n\t\tconst existing: Mark | undefined = block\n\t\t\t? findMarkInRange(block, markTypeName, from, to)\n\t\t\t: undefined;\n\t\tbuilder.removeMark(blockId, from, to, existing ?? { type: markTypeName });\n\t});\n\n\tbuilder.setSelection(sel);\n\treturn builder.build();\n}\n\n/**\n * Extracts a typed attribute value from the mark at the current selection.\n *\n * Looks at stored marks (collapsed w/ stored), block marks at cursor offset\n * (collapsed w/o stored), or anchor-block marks (range).\n *\n * @param extractFn — Narrows the found mark and returns the desired value,\n * or `null` when the mark's attrs don't match expectations.\n */\nexport function getMarkAttrAtSelection<K extends keyof MarkAttrRegistry, V>(\n\tstate: EditorState,\n\tmarkTypeName: K,\n\textractFn: (mark: Mark & { readonly type: K; readonly attrs: MarkAttrRegistry[K] }) => V | null,\n): V | null {\n\tconst sel = state.selection;\n\tif (!isTextSelection(sel)) return null;\n\n\t// Collapsed cursor honors stored marks and right-boundary inclusivity; a\n\t// range reads the raw content marks at its anchor.\n\tlet marks: readonly Mark[];\n\tif (isCollapsed(sel)) {\n\t\tmarks = resolveCursorMarks(state);\n\t} else {\n\t\tconst block = state.getBlock(sel.anchor.blockId);\n\t\tif (!block) return null;\n\t\tmarks = getBlockMarksAtOffset(block, sel.anchor.offset);\n\t}\n\n\tconst found = marks.find((m) => (m.type as string) === markTypeName);\n\treturn found && isMarkOfType(found, markTypeName) ? extractFn(found) : null;\n}\n\n/**\n * Returns `true` when the given attributed mark type is present at the\n * current selection (collapsed or range).\n */\nexport function isAttributedMarkActive<K extends keyof MarkAttrRegistry>(\n\tstate: EditorState,\n\tmarkTypeName: K,\n): boolean {\n\treturn getMarkAttrAtSelection(state, markTypeName, () => true as const) !== null;\n}\n\n/**\n * Finds the first mark of the given type within an offset range of a block.\n *\n * Returns the full mark (including attrs) so callers can pass it to\n * `removeMark` for correct undo inversion, or `undefined` when absent.\n */\nfunction findMarkInRange(\n\tblock: BlockNode,\n\ttypeName: MarkTypeName,\n\tfrom: number,\n\tto: number,\n): Mark | undefined {\n\tconst children: readonly (TextNode | InlineNode)[] = getInlineChildren(block);\n\tlet pos = 0;\n\n\tfor (const child of children) {\n\t\tif (!isTextNode(child)) {\n\t\t\tpos += 1;\n\t\t\tcontinue;\n\t\t}\n\t\tconst nodeEnd: number = pos + child.text.length;\n\t\tif (nodeEnd > from && pos < to) {\n\t\t\tconst found: Mark | undefined = child.marks.find((m) => m.type === typeName);\n\t\t\tif (found) return found;\n\t\t}\n\t\tpos = nodeEnd;\n\t}\n\treturn undefined;\n}\n"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- import{o as i,u as t}from"./Selection-HYoVFpAx.mjs";import{i as e}from"./TypeBrands-Ch9856Gb.mjs";import{r as o}from"./HTMLUtils-C6B4UT00.mjs";import{i as n,r,t as s}from"./AttributedMarkCommands-D4W2Jgpj.mjs";import{c as l,n as a,o as m,r as c}from"./PluginHelpers-KDuTlmXm.mjs";import{t as d}from"./ShortcutFormatting-TwiufqeV.mjs";import{t as g}from"./DirectionIcons-Bbawl9ei.mjs";import{t as p}from"./TextDirectionService-OFOU6r_s.mjs";var u={inlineLTR:"Inline LTR",inlineRTL:"Inline RTL",inlineAuto:"Inline Auto",inlineLabel:"Inline Direction",inlineTooltip:"Inline Direction",announceRemoveBidi:"Inline direction isolation removed"},h=/* #__PURE__ */Object.assign({"./locales/ar.ts":()=>import("./ar-B03uY4xr.mjs"),"./locales/de.ts":()=>import("./de-XCCpWyg0.mjs"),"./locales/es.ts":()=>import("./es-B0Za939C.mjs"),"./locales/fr.ts":()=>import("./fr-DciSEykY.mjs"),"./locales/hi.ts":()=>import("./hi-j3TDLMYd.mjs"),"./locales/pt.ts":()=>import("./pt-CEUgbrii.mjs"),"./locales/ru.ts":()=>import("./ru-BNPUT-3S.mjs"),"./locales/zh.ts":()=>import("./zh-Oj-qSUEp.mjs")});async function B(i){return l(h,i,u)}var v=class{id="bidi-isolation";name="Bidi Isolation";priority=92;config;locale;constructor(i){this.config={...i}}async init(i){this.locale=await m(i,this.config.locale,u,B),this.registerBdiMark(i),this.registerCommands(i),this.registerKeymaps(i),this.registerInlineToolbarItem(i)}registerBdiMark(i){i.registerMarkSpec({type:"bdi",rank:10,attrs:{dir:{default:"auto"}},toDOM(i){const t=document.createElement("bdi"),e=String(i.attrs?.dir??"auto");return t.setAttribute("dir",e),t},toHTMLString:(i,t)=>`<bdi dir="${o(String(i.attrs?.dir??"auto"))}">${t}</bdi>`,parseHTML:[{tag:"bdi",getAttrs:i=>{const t=i.getAttribute("dir");return"ltr"===t||"rtl"===t?{dir:t}:{dir:"auto"}}}],sanitize:{tags:["bdi"],attrs:["dir"]}})}registerCommands(i){i.registerCommand("toggleBidiLTR",()=>{const t=this.applyBdi(i,"ltr");return t&&i.announce(this.locale.inlineLTR),t}),i.registerCommand("toggleBidiRTL",()=>{const t=this.applyBdi(i,"rtl");return t&&i.announce(this.locale.inlineRTL),t}),i.registerCommand("toggleBidiAuto",()=>{const t=this.applyBdi(i,"auto");return t&&i.announce(this.locale.inlineAuto),t}),i.registerCommand("removeBidi",()=>{const t=this.removeBdi(i);return t&&i.announce(this.locale.announceRemoveBidi),t}),i.registerCommand("toggleBidiIsolation",()=>this.toggleBidiIsolation(i))}registerKeymaps(i){i.registerKeymap({"Mod-Shift-B":()=>i.executeCommand("toggleBidiIsolation")})}registerInlineToolbarItem(e){const o=[{label:this.locale.inlineLTR,command:"toggleBidiLTR",icon:g.ltr},{label:this.locale.inlineRTL,command:"toggleBidiRTL",icon:g.rtl},{label:this.locale.inlineAuto,command:"toggleBidiAuto",icon:g.auto},{label:this.locale.announceRemoveBidi,command:"removeBidi"}];e.registerToolbarItem({id:"inline-direction",group:"format",icon:'<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M10 4v7h2V4h2v7h2V4h1V2H10a3 3 0 1 0 0 6zm-3.5 9.5L3 17l3.5 3.5V18h3v-2h-3v-2.5zm14 0L17 17l3.5 3.5V18h-3v-2h3v-2.5zM11 16h2v6h-2z"/></svg>',label:this.locale.inlineLabel,tooltip:`${this.locale.inlineTooltip} (${d("Mod-Shift-B")})`,command:"toggleBidiIsolation",popupType:"dropdown",popupConfig:{items:o},isActive:i=>r(i,"bdi"),isEnabled:e=>{const o=e.selection;return t(o)&&!i(o)}})}toggleBidiIsolation(i){const t=i.getState();if(r(t,"bdi")){const t=this.removeBdi(i);return t&&i.announce(this.locale.announceRemoveBidi),t}const e=c(t),o=i.getService(p),n="rtl"===(e&&o?o.getBlockDir(e):"auto")?"ltr":"rtl",s=this.applyBdi(i,n);if(s){const t="ltr"===n?this.locale.inlineLTR:this.locale.inlineRTL;i.announce(t)}return s}applyBdi(i,t){return a(i,s(i.getState(),{type:e("bdi"),attrs:{dir:t}}))}removeBdi(i){return a(i,n(i.getState(),e("bdi")))}};export{u as n,B as r,v as t};
2
- //# sourceMappingURL=BidiIsolationPlugin-BddRbDCN.mjs.map
1
+ import{r as i}from"./HTMLUtils-Bhg3_P8B.mjs";import{o as t,u as e}from"./Selection-HYoVFpAx.mjs";import{i as o}from"./TypeBrands-Ch9856Gb.mjs";import{i as n,r,t as s}from"./AttributedMarkCommands-BCvmqeFZ.mjs";import{c as l,n as a,o as m,r as c}from"./PluginHelpers-KDuTlmXm.mjs";import{t as d}from"./ShortcutFormatting-TwiufqeV.mjs";import{t as g}from"./DirectionIcons-Bbawl9ei.mjs";import{t as p}from"./TextDirectionService-OFOU6r_s.mjs";var u={inlineLTR:"Inline LTR",inlineRTL:"Inline RTL",inlineAuto:"Inline Auto",inlineLabel:"Inline Direction",inlineTooltip:"Inline Direction",announceRemoveBidi:"Inline direction isolation removed"},h=/* #__PURE__ */Object.assign({"./locales/ar.ts":()=>import("./ar-B03uY4xr.mjs"),"./locales/de.ts":()=>import("./de-XCCpWyg0.mjs"),"./locales/es.ts":()=>import("./es-B0Za939C.mjs"),"./locales/fr.ts":()=>import("./fr-DciSEykY.mjs"),"./locales/hi.ts":()=>import("./hi-j3TDLMYd.mjs"),"./locales/pt.ts":()=>import("./pt-CEUgbrii.mjs"),"./locales/ru.ts":()=>import("./ru-BNPUT-3S.mjs"),"./locales/zh.ts":()=>import("./zh-Oj-qSUEp.mjs")});async function B(i){return l(h,i,u)}var b=class{id="bidi-isolation";name="Bidi Isolation";priority=92;config;locale;constructor(i){this.config={...i}}async init(i){this.locale=await m(i,this.config.locale,u,B),this.registerBdiMark(i),this.registerCommands(i),this.registerKeymaps(i),this.registerInlineToolbarItem(i)}registerBdiMark(t){t.registerMarkSpec({type:"bdi",rank:10,attrs:{dir:{default:"auto"}},toDOM(i){const t=document.createElement("bdi"),e=String(i.attrs?.dir??"auto");return t.setAttribute("dir",e),t},toHTMLString:(t,e)=>`<bdi dir="${i(String(t.attrs?.dir??"auto"))}">${e}</bdi>`,parseHTML:[{tag:"bdi",getAttrs:i=>{const t=i.getAttribute("dir");return"ltr"===t||"rtl"===t?{dir:t}:{dir:"auto"}}}],sanitize:{tags:["bdi"],attrs:["dir"]}})}registerCommands(i){i.registerCommand("toggleBidiLTR",()=>{const t=this.applyBdi(i,"ltr");return t&&i.announce(this.locale.inlineLTR),t}),i.registerCommand("toggleBidiRTL",()=>{const t=this.applyBdi(i,"rtl");return t&&i.announce(this.locale.inlineRTL),t}),i.registerCommand("toggleBidiAuto",()=>{const t=this.applyBdi(i,"auto");return t&&i.announce(this.locale.inlineAuto),t}),i.registerCommand("removeBidi",()=>{const t=this.removeBdi(i);return t&&i.announce(this.locale.announceRemoveBidi),t}),i.registerCommand("toggleBidiIsolation",()=>this.toggleBidiIsolation(i))}registerKeymaps(i){i.registerKeymap({"Mod-Shift-B":()=>i.executeCommand("toggleBidiIsolation")})}registerInlineToolbarItem(i){const o=[{label:this.locale.inlineLTR,command:"toggleBidiLTR",icon:g.ltr},{label:this.locale.inlineRTL,command:"toggleBidiRTL",icon:g.rtl},{label:this.locale.inlineAuto,command:"toggleBidiAuto",icon:g.auto},{label:this.locale.announceRemoveBidi,command:"removeBidi"}];i.registerToolbarItem({id:"inline-direction",group:"format",icon:'<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M10 4v7h2V4h2v7h2V4h1V2H10a3 3 0 1 0 0 6zm-3.5 9.5L3 17l3.5 3.5V18h3v-2h-3v-2.5zm14 0L17 17l3.5 3.5V18h-3v-2h3v-2.5zM11 16h2v6h-2z"/></svg>',label:this.locale.inlineLabel,tooltip:`${this.locale.inlineTooltip} (${d("Mod-Shift-B")})`,command:"toggleBidiIsolation",popupType:"dropdown",popupConfig:{items:o},isActive:i=>r(i,"bdi"),isEnabled:i=>{const o=i.selection;return e(o)&&!t(o)}})}toggleBidiIsolation(i){const t=i.getState();if(r(t,"bdi")){const t=this.removeBdi(i);return t&&i.announce(this.locale.announceRemoveBidi),t}const e=c(t),o=i.getService(p),n="rtl"===(e&&o?o.getBlockDir(e):"auto")?"ltr":"rtl",s=this.applyBdi(i,n);if(s){const t="ltr"===n?this.locale.inlineLTR:this.locale.inlineRTL;i.announce(t)}return s}applyBdi(i,t){return a(i,s(i.getState(),{type:o("bdi"),attrs:{dir:t}}))}removeBdi(i){return a(i,n(i.getState(),o("bdi")))}};export{u as n,B as r,b as t};
2
+ //# sourceMappingURL=BidiIsolationPlugin-Cw2KMk-H.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"BidiIsolationPlugin-BddRbDCN.mjs","names":[],"sources":["../../src/plugins/bidi-isolation/BidiIsolationLocale.ts","../../src/plugins/bidi-isolation/BidiIsolationPlugin.ts"],"sourcesContent":["/** Locale interface and default English locale for the BidiIsolationPlugin. */\n\nimport { type LocaleModuleMap, loadLocaleModule } from '../shared/LocaleLoader.js';\n\nexport interface BidiIsolationLocale {\n\treadonly inlineLTR: string;\n\treadonly inlineRTL: string;\n\treadonly inlineAuto: string;\n\treadonly inlineLabel: string;\n\treadonly inlineTooltip: string;\n\treadonly announceRemoveBidi: string;\n}\n\nexport const BIDI_ISOLATION_LOCALE_EN: BidiIsolationLocale = {\n\tinlineLTR: 'Inline LTR',\n\tinlineRTL: 'Inline RTL',\n\tinlineAuto: 'Inline Auto',\n\tinlineLabel: 'Inline Direction',\n\tinlineTooltip: 'Inline Direction',\n\tannounceRemoveBidi: 'Inline direction isolation removed',\n};\n\nconst localeModules: LocaleModuleMap<BidiIsolationLocale> = import.meta.glob<{\n\tdefault: BidiIsolationLocale;\n}>('./locales/*.ts', { eager: false });\n\nexport async function loadBidiIsolationLocale(lang: string): Promise<BidiIsolationLocale> {\n\treturn loadLocaleModule(localeModules, lang, BIDI_ISOLATION_LOCALE_EN);\n}\n","/**\n * Inline bidi isolation plugin: registers a `<bdi>` mark and the inline\n * commands / toolbar / keymap that wrap selected text in a `<bdi>` element\n * with an explicit `dir` attribute.\n *\n * Use alongside {@link TextDirectionPlugin} for the full RTL story:\n * block-level direction lives there, the optional `TextDirectionService`\n * lets this plugin pick the inline direction opposite to the block direction\n * in `toggleBidiIsolation`. Without `TextDirectionPlugin`, this plugin\n * still works — `toggleBidiIsolation` falls back to applying `'rtl'`.\n */\n\nimport {\n\tapplyAttributedMark,\n\tisAttributedMarkActive,\n\tremoveAttributedMark,\n} from '../../commands/AttributedMarkCommands.js';\nimport { escapeHTML } from '../../model/HTMLUtils.js';\nimport { isCollapsed, isTextSelection } from '../../model/Selection.js';\nimport { markType } from '../../model/TypeBrands.js';\nimport type { Plugin, PluginContext } from '../Plugin.js';\nimport { dispatchIfPresent, getSelectedBlock, resolveLocale } from '../shared/PluginHelpers.js';\nimport { formatShortcut } from '../shared/ShortcutFormatting.js';\nimport { DIRECTION_ICONS } from '../text-direction/DirectionIcons.js';\nimport {\n\tTEXT_DIRECTION_SERVICE_KEY,\n\ttype TextDirection,\n\ttype TextDirectionService,\n} from '../text-direction/TextDirectionService.js';\nimport {\n\tBIDI_ISOLATION_LOCALE_EN,\n\ttype BidiIsolationLocale,\n\tloadBidiIsolationLocale,\n} from './BidiIsolationLocale.js';\n\ndeclare module '../../model/AttrRegistry.js' {\n\tinterface MarkAttrRegistry {\n\t\tbdi: { dir: 'ltr' | 'rtl' | 'auto' };\n\t}\n}\n\nexport interface BidiIsolationConfig {\n\treadonly locale?: BidiIsolationLocale;\n}\n\nconst INLINE_BDI_ICON: string =\n\t'<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\"><path d=\"M10 4v7h2V4h2v7h2V4h1V2H10a3 3 0 1 0 0 6zm-3.5 9.5L3 17l3.5 3.5V18h3v-2h-3v-2.5zm14 0L17 17l3.5 3.5V18h-3v-2h3v-2.5zM11 16h2v6h-2z\"/></svg>';\n\nexport class BidiIsolationPlugin implements Plugin {\n\treadonly id = 'bidi-isolation';\n\treadonly name = 'Bidi Isolation';\n\treadonly priority = 92;\n\n\tprivate readonly config: BidiIsolationConfig;\n\tprivate locale!: BidiIsolationLocale;\n\n\tconstructor(config?: Partial<BidiIsolationConfig>) {\n\t\tthis.config = { ...config };\n\t}\n\n\tasync init(context: PluginContext): Promise<void> {\n\t\tthis.locale = await resolveLocale(\n\t\t\tcontext,\n\t\t\tthis.config.locale,\n\t\t\tBIDI_ISOLATION_LOCALE_EN,\n\t\t\tloadBidiIsolationLocale,\n\t\t);\n\n\t\tthis.registerBdiMark(context);\n\t\tthis.registerCommands(context);\n\t\tthis.registerKeymaps(context);\n\t\tthis.registerInlineToolbarItem(context);\n\t}\n\n\tprivate registerBdiMark(context: PluginContext): void {\n\t\tcontext.registerMarkSpec({\n\t\t\ttype: 'bdi',\n\t\t\trank: 10,\n\t\t\tattrs: {\n\t\t\t\tdir: { default: 'auto' },\n\t\t\t},\n\t\t\ttoDOM(mark) {\n\t\t\t\tconst el: HTMLElement = document.createElement('bdi');\n\t\t\t\tconst dir: string = String(mark.attrs?.dir ?? 'auto');\n\t\t\t\tel.setAttribute('dir', dir);\n\t\t\t\treturn el;\n\t\t\t},\n\t\t\ttoHTMLString: (mark, content) => {\n\t\t\t\tconst dir: string = escapeHTML(String(mark.attrs?.dir ?? 'auto'));\n\t\t\t\treturn `<bdi dir=\"${dir}\">${content}</bdi>`;\n\t\t\t},\n\t\t\tparseHTML: [\n\t\t\t\t{\n\t\t\t\t\ttag: 'bdi',\n\t\t\t\t\tgetAttrs: (el) => {\n\t\t\t\t\t\tconst dir: string | null = el.getAttribute('dir');\n\t\t\t\t\t\tif (dir === 'ltr' || dir === 'rtl') return { dir };\n\t\t\t\t\t\treturn { dir: 'auto' };\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t],\n\t\t\tsanitize: { tags: ['bdi'], attrs: ['dir'] },\n\t\t});\n\t}\n\n\tprivate registerCommands(context: PluginContext): void {\n\t\tcontext.registerCommand('toggleBidiLTR', () => {\n\t\t\tconst result: boolean = this.applyBdi(context, 'ltr');\n\t\t\tif (result) context.announce(this.locale.inlineLTR);\n\t\t\treturn result;\n\t\t});\n\n\t\tcontext.registerCommand('toggleBidiRTL', () => {\n\t\t\tconst result: boolean = this.applyBdi(context, 'rtl');\n\t\t\tif (result) context.announce(this.locale.inlineRTL);\n\t\t\treturn result;\n\t\t});\n\n\t\tcontext.registerCommand('toggleBidiAuto', () => {\n\t\t\tconst result: boolean = this.applyBdi(context, 'auto');\n\t\t\tif (result) context.announce(this.locale.inlineAuto);\n\t\t\treturn result;\n\t\t});\n\n\t\tcontext.registerCommand('removeBidi', () => {\n\t\t\tconst result: boolean = this.removeBdi(context);\n\t\t\tif (result) context.announce(this.locale.announceRemoveBidi);\n\t\t\treturn result;\n\t\t});\n\n\t\tcontext.registerCommand('toggleBidiIsolation', () => {\n\t\t\treturn this.toggleBidiIsolation(context);\n\t\t});\n\t}\n\n\tprivate registerKeymaps(context: PluginContext): void {\n\t\tcontext.registerKeymap({\n\t\t\t'Mod-Shift-B': () => context.executeCommand('toggleBidiIsolation'),\n\t\t});\n\t}\n\n\tprivate registerInlineToolbarItem(context: PluginContext): void {\n\t\tconst inlineItems = [\n\t\t\t{ label: this.locale.inlineLTR, command: 'toggleBidiLTR', icon: DIRECTION_ICONS.ltr },\n\t\t\t{ label: this.locale.inlineRTL, command: 'toggleBidiRTL', icon: DIRECTION_ICONS.rtl },\n\t\t\t{ label: this.locale.inlineAuto, command: 'toggleBidiAuto', icon: DIRECTION_ICONS.auto },\n\t\t\t{ label: this.locale.announceRemoveBidi, command: 'removeBidi' },\n\t\t];\n\n\t\tcontext.registerToolbarItem({\n\t\t\tid: 'inline-direction',\n\t\t\tgroup: 'format',\n\t\t\ticon: INLINE_BDI_ICON,\n\t\t\tlabel: this.locale.inlineLabel,\n\t\t\ttooltip: `${this.locale.inlineTooltip} (${formatShortcut('Mod-Shift-B')})`,\n\t\t\tcommand: 'toggleBidiIsolation',\n\t\t\tpopupType: 'dropdown',\n\t\t\tpopupConfig: { items: inlineItems },\n\t\t\tisActive: (state) => isAttributedMarkActive(state, 'bdi'),\n\t\t\tisEnabled: (state) => {\n\t\t\t\tconst sel = state.selection;\n\t\t\t\treturn isTextSelection(sel) && !isCollapsed(sel);\n\t\t\t},\n\t\t});\n\t}\n\n\t/**\n\t * Cycles inline bidi isolation: no-bdi → bdi (opposite of block dir) →\n\t * remove. When the {@link TextDirectionService} is registered, picks the\n\t * direction opposite to the current block; otherwise defaults to `'rtl'`.\n\t */\n\tprivate toggleBidiIsolation(context: PluginContext): boolean {\n\t\tconst state = context.getState();\n\t\tif (isAttributedMarkActive(state, 'bdi')) {\n\t\t\tconst result: boolean = this.removeBdi(context);\n\t\t\tif (result) context.announce(this.locale.announceRemoveBidi);\n\t\t\treturn result;\n\t\t}\n\n\t\tconst block = getSelectedBlock(state);\n\t\tconst directionService: TextDirectionService | undefined = context.getService(\n\t\t\tTEXT_DIRECTION_SERVICE_KEY,\n\t\t);\n\t\tconst blockDir: TextDirection =\n\t\t\tblock && directionService ? directionService.getBlockDir(block) : 'auto';\n\t\tconst bdiDir: TextDirection = blockDir === 'rtl' ? 'ltr' : 'rtl';\n\n\t\tconst result: boolean = this.applyBdi(context, bdiDir);\n\t\tif (result) {\n\t\t\tconst announcement: string = bdiDir === 'ltr' ? this.locale.inlineLTR : this.locale.inlineRTL;\n\t\t\tcontext.announce(announcement);\n\t\t}\n\t\treturn result;\n\t}\n\n\tprivate applyBdi(context: PluginContext, dir: TextDirection): boolean {\n\t\tconst state = context.getState();\n\t\tconst mark = { type: markType('bdi'), attrs: { dir } };\n\t\treturn dispatchIfPresent(context, applyAttributedMark(state, mark));\n\t}\n\n\tprivate removeBdi(context: PluginContext): boolean {\n\t\tconst state = context.getState();\n\t\treturn dispatchIfPresent(context, removeAttributedMark(state, markType('bdi')));\n\t}\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"BidiIsolationPlugin-Cw2KMk-H.mjs","names":[],"sources":["../../src/plugins/bidi-isolation/BidiIsolationLocale.ts","../../src/plugins/bidi-isolation/BidiIsolationPlugin.ts"],"sourcesContent":["/** Locale interface and default English locale for the BidiIsolationPlugin. */\n\nimport { type LocaleModuleMap, loadLocaleModule } from '../shared/LocaleLoader.js';\n\nexport interface BidiIsolationLocale {\n\treadonly inlineLTR: string;\n\treadonly inlineRTL: string;\n\treadonly inlineAuto: string;\n\treadonly inlineLabel: string;\n\treadonly inlineTooltip: string;\n\treadonly announceRemoveBidi: string;\n}\n\nexport const BIDI_ISOLATION_LOCALE_EN: BidiIsolationLocale = {\n\tinlineLTR: 'Inline LTR',\n\tinlineRTL: 'Inline RTL',\n\tinlineAuto: 'Inline Auto',\n\tinlineLabel: 'Inline Direction',\n\tinlineTooltip: 'Inline Direction',\n\tannounceRemoveBidi: 'Inline direction isolation removed',\n};\n\nconst localeModules: LocaleModuleMap<BidiIsolationLocale> = import.meta.glob<{\n\tdefault: BidiIsolationLocale;\n}>('./locales/*.ts', { eager: false });\n\nexport async function loadBidiIsolationLocale(lang: string): Promise<BidiIsolationLocale> {\n\treturn loadLocaleModule(localeModules, lang, BIDI_ISOLATION_LOCALE_EN);\n}\n","/**\n * Inline bidi isolation plugin: registers a `<bdi>` mark and the inline\n * commands / toolbar / keymap that wrap selected text in a `<bdi>` element\n * with an explicit `dir` attribute.\n *\n * Use alongside {@link TextDirectionPlugin} for the full RTL story:\n * block-level direction lives there, the optional `TextDirectionService`\n * lets this plugin pick the inline direction opposite to the block direction\n * in `toggleBidiIsolation`. Without `TextDirectionPlugin`, this plugin\n * still works — `toggleBidiIsolation` falls back to applying `'rtl'`.\n */\n\nimport {\n\tapplyAttributedMark,\n\tisAttributedMarkActive,\n\tremoveAttributedMark,\n} from '../../commands/AttributedMarkCommands.js';\nimport { escapeHTML } from '../../model/HTMLUtils.js';\nimport { isCollapsed, isTextSelection } from '../../model/Selection.js';\nimport { markType } from '../../model/TypeBrands.js';\nimport type { Plugin, PluginContext } from '../Plugin.js';\nimport { dispatchIfPresent, getSelectedBlock, resolveLocale } from '../shared/PluginHelpers.js';\nimport { formatShortcut } from '../shared/ShortcutFormatting.js';\nimport { DIRECTION_ICONS } from '../text-direction/DirectionIcons.js';\nimport {\n\tTEXT_DIRECTION_SERVICE_KEY,\n\ttype TextDirection,\n\ttype TextDirectionService,\n} from '../text-direction/TextDirectionService.js';\nimport {\n\tBIDI_ISOLATION_LOCALE_EN,\n\ttype BidiIsolationLocale,\n\tloadBidiIsolationLocale,\n} from './BidiIsolationLocale.js';\n\ndeclare module '../../model/AttrRegistry.js' {\n\tinterface MarkAttrRegistry {\n\t\tbdi: { dir: 'ltr' | 'rtl' | 'auto' };\n\t}\n}\n\nexport interface BidiIsolationConfig {\n\treadonly locale?: BidiIsolationLocale;\n}\n\nconst INLINE_BDI_ICON: string =\n\t'<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\"><path d=\"M10 4v7h2V4h2v7h2V4h1V2H10a3 3 0 1 0 0 6zm-3.5 9.5L3 17l3.5 3.5V18h3v-2h-3v-2.5zm14 0L17 17l3.5 3.5V18h-3v-2h3v-2.5zM11 16h2v6h-2z\"/></svg>';\n\nexport class BidiIsolationPlugin implements Plugin {\n\treadonly id = 'bidi-isolation';\n\treadonly name = 'Bidi Isolation';\n\treadonly priority = 92;\n\n\tprivate readonly config: BidiIsolationConfig;\n\tprivate locale!: BidiIsolationLocale;\n\n\tconstructor(config?: Partial<BidiIsolationConfig>) {\n\t\tthis.config = { ...config };\n\t}\n\n\tasync init(context: PluginContext): Promise<void> {\n\t\tthis.locale = await resolveLocale(\n\t\t\tcontext,\n\t\t\tthis.config.locale,\n\t\t\tBIDI_ISOLATION_LOCALE_EN,\n\t\t\tloadBidiIsolationLocale,\n\t\t);\n\n\t\tthis.registerBdiMark(context);\n\t\tthis.registerCommands(context);\n\t\tthis.registerKeymaps(context);\n\t\tthis.registerInlineToolbarItem(context);\n\t}\n\n\tprivate registerBdiMark(context: PluginContext): void {\n\t\tcontext.registerMarkSpec({\n\t\t\ttype: 'bdi',\n\t\t\trank: 10,\n\t\t\tattrs: {\n\t\t\t\tdir: { default: 'auto' },\n\t\t\t},\n\t\t\ttoDOM(mark) {\n\t\t\t\tconst el: HTMLElement = document.createElement('bdi');\n\t\t\t\tconst dir: string = String(mark.attrs?.dir ?? 'auto');\n\t\t\t\tel.setAttribute('dir', dir);\n\t\t\t\treturn el;\n\t\t\t},\n\t\t\ttoHTMLString: (mark, content) => {\n\t\t\t\tconst dir: string = escapeHTML(String(mark.attrs?.dir ?? 'auto'));\n\t\t\t\treturn `<bdi dir=\"${dir}\">${content}</bdi>`;\n\t\t\t},\n\t\t\tparseHTML: [\n\t\t\t\t{\n\t\t\t\t\ttag: 'bdi',\n\t\t\t\t\tgetAttrs: (el) => {\n\t\t\t\t\t\tconst dir: string | null = el.getAttribute('dir');\n\t\t\t\t\t\tif (dir === 'ltr' || dir === 'rtl') return { dir };\n\t\t\t\t\t\treturn { dir: 'auto' };\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t],\n\t\t\tsanitize: { tags: ['bdi'], attrs: ['dir'] },\n\t\t});\n\t}\n\n\tprivate registerCommands(context: PluginContext): void {\n\t\tcontext.registerCommand('toggleBidiLTR', () => {\n\t\t\tconst result: boolean = this.applyBdi(context, 'ltr');\n\t\t\tif (result) context.announce(this.locale.inlineLTR);\n\t\t\treturn result;\n\t\t});\n\n\t\tcontext.registerCommand('toggleBidiRTL', () => {\n\t\t\tconst result: boolean = this.applyBdi(context, 'rtl');\n\t\t\tif (result) context.announce(this.locale.inlineRTL);\n\t\t\treturn result;\n\t\t});\n\n\t\tcontext.registerCommand('toggleBidiAuto', () => {\n\t\t\tconst result: boolean = this.applyBdi(context, 'auto');\n\t\t\tif (result) context.announce(this.locale.inlineAuto);\n\t\t\treturn result;\n\t\t});\n\n\t\tcontext.registerCommand('removeBidi', () => {\n\t\t\tconst result: boolean = this.removeBdi(context);\n\t\t\tif (result) context.announce(this.locale.announceRemoveBidi);\n\t\t\treturn result;\n\t\t});\n\n\t\tcontext.registerCommand('toggleBidiIsolation', () => {\n\t\t\treturn this.toggleBidiIsolation(context);\n\t\t});\n\t}\n\n\tprivate registerKeymaps(context: PluginContext): void {\n\t\tcontext.registerKeymap({\n\t\t\t'Mod-Shift-B': () => context.executeCommand('toggleBidiIsolation'),\n\t\t});\n\t}\n\n\tprivate registerInlineToolbarItem(context: PluginContext): void {\n\t\tconst inlineItems = [\n\t\t\t{ label: this.locale.inlineLTR, command: 'toggleBidiLTR', icon: DIRECTION_ICONS.ltr },\n\t\t\t{ label: this.locale.inlineRTL, command: 'toggleBidiRTL', icon: DIRECTION_ICONS.rtl },\n\t\t\t{ label: this.locale.inlineAuto, command: 'toggleBidiAuto', icon: DIRECTION_ICONS.auto },\n\t\t\t{ label: this.locale.announceRemoveBidi, command: 'removeBidi' },\n\t\t];\n\n\t\tcontext.registerToolbarItem({\n\t\t\tid: 'inline-direction',\n\t\t\tgroup: 'format',\n\t\t\ticon: INLINE_BDI_ICON,\n\t\t\tlabel: this.locale.inlineLabel,\n\t\t\ttooltip: `${this.locale.inlineTooltip} (${formatShortcut('Mod-Shift-B')})`,\n\t\t\tcommand: 'toggleBidiIsolation',\n\t\t\tpopupType: 'dropdown',\n\t\t\tpopupConfig: { items: inlineItems },\n\t\t\tisActive: (state) => isAttributedMarkActive(state, 'bdi'),\n\t\t\tisEnabled: (state) => {\n\t\t\t\tconst sel = state.selection;\n\t\t\t\treturn isTextSelection(sel) && !isCollapsed(sel);\n\t\t\t},\n\t\t});\n\t}\n\n\t/**\n\t * Cycles inline bidi isolation: no-bdi → bdi (opposite of block dir) →\n\t * remove. When the {@link TextDirectionService} is registered, picks the\n\t * direction opposite to the current block; otherwise defaults to `'rtl'`.\n\t */\n\tprivate toggleBidiIsolation(context: PluginContext): boolean {\n\t\tconst state = context.getState();\n\t\tif (isAttributedMarkActive(state, 'bdi')) {\n\t\t\tconst result: boolean = this.removeBdi(context);\n\t\t\tif (result) context.announce(this.locale.announceRemoveBidi);\n\t\t\treturn result;\n\t\t}\n\n\t\tconst block = getSelectedBlock(state);\n\t\tconst directionService: TextDirectionService | undefined = context.getService(\n\t\t\tTEXT_DIRECTION_SERVICE_KEY,\n\t\t);\n\t\tconst blockDir: TextDirection =\n\t\t\tblock && directionService ? directionService.getBlockDir(block) : 'auto';\n\t\tconst bdiDir: TextDirection = blockDir === 'rtl' ? 'ltr' : 'rtl';\n\n\t\tconst result: boolean = this.applyBdi(context, bdiDir);\n\t\tif (result) {\n\t\t\tconst announcement: string = bdiDir === 'ltr' ? this.locale.inlineLTR : this.locale.inlineRTL;\n\t\t\tcontext.announce(announcement);\n\t\t}\n\t\treturn result;\n\t}\n\n\tprivate applyBdi(context: PluginContext, dir: TextDirection): boolean {\n\t\tconst state = context.getState();\n\t\tconst mark = { type: markType('bdi'), attrs: { dir } };\n\t\treturn dispatchIfPresent(context, applyAttributedMark(state, mark));\n\t}\n\n\tprivate removeBdi(context: PluginContext): boolean {\n\t\tconst state = context.getState();\n\t\treturn dispatchIfPresent(context, removeAttributedMark(state, markType('bdi')));\n\t}\n}\n"],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import{o as t}from"./HTMLUtils-Bhg3_P8B.mjs";import{C as n,E as e,M as r,N as o,_ as s,f as i,h as c,l as a,o as f,w as u}from"./Document-827l3P80.mjs";import{r as d}from"./NodeResolver-Dleih-8R.mjs";import{c as l,d as p,l as h,o as m,r as g,t as y}from"./Selection-HYoVFpAx.mjs";import{a as I,r as b}from"./TypeBrands-Ch9856Gb.mjs";import{i as k}from"./NavigationQueries-Bt4zZ17v.mjs";import{t as v}from"./ContentModel-NpAj7vGW.mjs";function x(t,n){if(0===n.length)return t.doc.children;const e=t.getBlock(n[n.length-1]);return e?e.children:[]}function N(t,n){if(m(t))return{blockId:t.anchor.blockId,offset:t.anchor.offset};const e=p(t,n);return{blockId:e.from.blockId,offset:e.from.offset}}function j(t){return t&&t.length>1?t.slice(0,-1):[]}function P(t,n){return t.findIndex(t=>u(t)&&t.id===n)}function A(t,n){const e=j(d(t.doc,n)),r=x(t,e);return{parentPath:e,siblings:r,index:P(r,n)}}function B(t){if(e(t))return t.id;for(const n of t.children)if(u(n))return B(n);return t.id}function T(t){if(e(t))return t.id;for(let n=t.children.length-1;n>=0;n--){const e=t.children[n];if(e&&u(e))return T(e)}return t.id}function E(t,n,e){const r=t.getBlock(n);if(!r)return null;if(k(t,n)){const e=t.getNodePath(n);return e?g(n,e):null}const o="start"===e?B(r):T(r),s=t.getBlock(o);return s?y(o,"start"===e?0:c(s)):null}function S(t,n,e){const r=t.doc.children,o="start"===n?r.map((t,n)=>n):r.map((t,n)=>r.length-1-n);for(const s of o){const o=r[s];if(!o||!u(o))continue;if(void 0!==e&&o.id===e)continue;const i=E(t,o.id,n);if(i)return i}return null}function _(t,n,e){const r=j(d(t.doc,n)),o=P(x(t,r),n);if(!(o<0))return{parentPath:r,anchorIndex:o,isAnchorEmpty:G(t,n,e)}}function w(t,n,e,r){const o=d(t.doc,e);if(!o)return;const s=t.getBlock(e);return s?{parentPath:o,anchorIndex:s.children.findIndex(t=>u(t)&&t.id===n),isAnchorEmpty:G(t,n,r)}:void 0}function C(t,n){if("table_cell"===t.getBlock(n)?.type)return n;const e=d(t.doc,n);if(e)for(const r of e)if("table_cell"===t.getBlock(r)?.type)return r}function M(t){return h(t)?t.nodeId:l(t)?t.blockId:t.anchor.blockId}function F(t,n,e,r,o,s){const i=C(t,e);if(i){const o=w(t,e,i,s);if(!o)return!1;const c=o.anchorIndex+1;n.insertNode(o.parentPath,c,r),o.isAnchorEmpty&&o.anchorIndex>=0&&n.removeNode(o.parentPath,o.anchorIndex)}else{const i=_(t,e,s);if(!i)return!1;const c=l(o)&&"before"===o.side?0:1;n.insertNode(i.parentPath,i.anchorIndex+c,r),i.isAnchorEmpty&&!l(o)&&n.removeNode(i.parentPath,i.anchorIndex)}return!0}function O(t,n){const e=d(t.doc,n),r=e&&e.length>0?e[0]:n;return t.doc.children.findIndex(t=>t.id===r)}function z(t,n,e){return!n||e.every(e=>v(t,n,e.type))}function D(t,n){const e=O(t,n);if(-1!==e)return{parentPath:[],anchorIndex:e,isAnchorEmpty:!1}}function H(t){return"paragraph"===t.type&&0===c(t)}function L(t,n,e,r){return Q(t,n,e,[r])}function Q(t,n,e,r){if(0===r.length)return;const o=O(t,e);if(-1===o)return;const s=t.doc.children[o],i=t.doc.children[o+1];let c=o+1;for(const f of r)n.insertNode([],c,f),c++;const a=s&&k(t,s.id)&&i&&H(i)?i:void 0;let u;return a?u=a:(u=f(I("paragraph")),n.insertNode([],c,u)),s&&H(s)&&n.removeNode([],o),u}function R(t,n){const e=t.children.map(t=>u(t)?R(t,i()):t);return f(t.type,e,n,t.attrs,t.htmlId)}function U(t,n){if(t.id===n)return t;for(const e of t.children){if(!u(e))continue;const t=U(e,n);if(t)return t}}function V(t,n,e=!1){if(!n)return;const r={};let o=!1;for(const s of Object.keys(n)){const i=n[s],c=t?.[s];"string"==typeof c||"number"==typeof c&&Number.isFinite(c)||"boolean"==typeof c?r[s]=c:e&&i.allowArray&&q(c)?r[s]=Object.freeze([...c]):void 0!==i.default&&(r[s]=i.default),s in r&&(o=!0)}return o?r:void 0}function q(t){return Array.isArray(t)&&t.every(t=>null===t||"string"==typeof t||"boolean"==typeof t||"number"==typeof t&&Number.isFinite(t))}function G(t,n,e){const r=t.getBlock(n);return!!r&&!(e?.getNodeSpec(r.type))?.isVoid&&""===s(r)}function J(n,e){if(!n.type)return;if(!e)return n;const r=e.getNodeSpec(n.type);if(!r)return;const o=V(n.attrs,r.attrs,!0),s=t(n.htmlId),i=n.segments?function(t,n){const e=[];for(const r of t){if("inline"===r.kind){const t=n.getInlineNodeSpec(r.inlineType);if(!t)continue;const o=V(r.attrs,t.attrs);e.push({kind:"inline",inlineType:r.inlineType,...o?{attrs:o}:{}});continue}e.push(r)}return e}(n.segments,e):void 0,{htmlId:c,...a}=n;return{...a,...s?{htmlId:s}:{},...o?{attrs:o}:{},...i?{segments:i}:n.segments?{segments:[]}:{}}}function K(t){const n=i(),e=function(t){const n=Y(t);return 0===n.length?void 0:r(n)}(t),o=t.attrs?t.attrs:void 0;return f(I(t.type),e,n,o,t.htmlId)}function W(t,n){const e=[];for(const r of t){const t=J(r,n);t&&e.push(X(t))}return{blocks:e}}function X(t){const n=t.attrs?t.attrs:void 0;return{type:I(t.type),...n?{attrs:n}:{},segments:Y(t)}}function Y(t){if(t.segments&&t.segments.length>0)return function(t){const e=[];for(const r of t){if("inline"===r.kind){e.push(n(a(b(r.inlineType),r.attrs)));continue}if(0===r.text.length)continue;const t=r.marks.map(t=>({type:t.type,...t.attrs?{attrs:t.attrs}:{}}));e.push(o(r.text,t))}return e}(t.segments);const e=t.text??"";return e?[o(e)]:[]}export{x as C,P as S,A as T,E as _,C as a,B as b,Q as c,w as d,D as f,J as g,V as h,U as i,H as l,W as m,R as n,F as o,_ as p,K as r,L as s,z as t,M as u,S as v,N as w,T as x,j as y};
2
+ //# sourceMappingURL=BlockInsertion-CYH2gRkY.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BlockInsertion-CYH2gRkY.mjs","names":[],"sources":["../../src/commands/CommandHelpers.ts","../../src/commands/BlockInsertion.ts"],"sourcesContent":["/**\n * Shared helpers used across multiple command modules.\n *\n * - {@link getSiblings} — resolves a parent path to its child list\n * - {@link resolveInsertPoint} — normalizes a text selection to a single insert position\n */\n\nimport type { BlockNode, ChildNode, Document } from '../model/Document.js';\nimport { getBlockLength, isBlockNode, isLeafBlock } from '../model/Document.js';\nimport { findNodePath } from '../model/NodeResolver.js';\nimport {\n\tcreateCollapsedSelection,\n\tcreateNodeSelection,\n\tisCollapsed,\n\tselectionRange,\n} from '../model/Selection.js';\nimport type { EditorSelection, Selection } from '../model/Selection.js';\nimport type { BlockId } from '../model/TypeBrands.js';\nimport type { EditorState } from '../state/EditorState.js';\nimport { isVoidBlock } from '../state/NavigationQueries.js';\n\n/** The resolved insert position within a single block. */\nexport interface InsertPoint {\n\treadonly blockId: BlockId;\n\treadonly offset: number;\n}\n\n/** Resolves the children of a parent path: doc root or a nested block. */\nexport function getSiblings(\n\tstate: EditorState,\n\tparentPath: readonly BlockId[],\n): readonly ChildNode[] {\n\tif (parentPath.length === 0) return state.doc.children;\n\tconst parent: BlockNode | undefined = state.getBlock(\n\t\tparentPath[parentPath.length - 1] as BlockId,\n\t);\n\treturn parent ? parent.children : [];\n}\n\n/**\n * Normalizes a text selection to a single insert point.\n *\n * - Collapsed selection → anchor position.\n * - Range selection → normalized `from` position (document-order start).\n */\nexport function resolveInsertPoint(sel: Selection, blockOrder: readonly BlockId[]): InsertPoint {\n\tif (isCollapsed(sel)) {\n\t\treturn { blockId: sel.anchor.blockId, offset: sel.anchor.offset };\n\t}\n\tconst range = selectionRange(sel, blockOrder);\n\treturn { blockId: range.from.blockId, offset: range.from.offset };\n}\n\n/** Extracts the parent path from a full node path (all elements except the last). */\nexport function extractParentPath(path: readonly string[] | undefined): BlockId[] {\n\treturn path && path.length > 1 ? (path.slice(0, -1) as BlockId[]) : [];\n}\n\n/** Finds the index of a block by ID within a sibling list. */\nexport function findSiblingIndex(siblings: readonly ChildNode[], targetId: BlockId): number {\n\treturn siblings.findIndex((c) => isBlockNode(c) && c.id === targetId);\n}\n\n/** A block's parent path, its sibling list, and its index within that list. */\nexport interface SiblingContext {\n\treadonly parentPath: BlockId[];\n\treadonly siblings: readonly ChildNode[];\n\treadonly index: number;\n}\n\n/**\n * Resolves a node's parent path, sibling list, and index among its siblings.\n * `index` is `-1` when the node is not found; callers that require the node to\n * exist should guard on `index < 0`.\n */\nexport function resolveSiblingContext(state: EditorState, nodeId: BlockId): SiblingContext {\n\tconst parentPath: BlockId[] = extractParentPath(findNodePath(state.doc, nodeId));\n\tconst siblings: readonly ChildNode[] = getSiblings(state, parentPath);\n\tconst index: number = findSiblingIndex(siblings, nodeId);\n\treturn { parentPath, siblings, index };\n}\n\n/** Finds the first leaf block ID in a subtree. */\nexport function findFirstLeafBlockId(node: BlockNode): BlockId {\n\tif (isLeafBlock(node)) return node.id;\n\n\tfor (const child of node.children) {\n\t\tif (!isBlockNode(child)) continue;\n\t\treturn findFirstLeafBlockId(child);\n\t}\n\n\treturn node.id;\n}\n\n/** Finds the last leaf block ID in a subtree. */\nexport function findLastLeafBlockId(node: BlockNode): BlockId {\n\tif (isLeafBlock(node)) return node.id;\n\n\tfor (let i = node.children.length - 1; i >= 0; i--) {\n\t\tconst child = node.children[i];\n\t\tif (child && isBlockNode(child)) {\n\t\t\treturn findLastLeafBlockId(child);\n\t\t}\n\t}\n\n\treturn node.id;\n}\n\n/**\n * Resolves a valid editor selection at the start or end of a block subtree.\n * Void blocks become NodeSelections; text-capable blocks resolve to leaf cursors.\n */\nexport function createSelectionForBlockBoundary(\n\tstate: EditorState,\n\tblockId: BlockId,\n\tboundary: 'start' | 'end',\n): EditorSelection | null {\n\tconst block = state.getBlock(blockId);\n\tif (!block) return null;\n\n\tif (isVoidBlock(state, blockId)) {\n\t\tconst path = state.getNodePath(blockId);\n\t\treturn path ? createNodeSelection(blockId, path) : null;\n\t}\n\n\tconst leafId: BlockId =\n\t\tboundary === 'start' ? findFirstLeafBlockId(block) : findLastLeafBlockId(block);\n\tconst leaf = state.getBlock(leafId);\n\tif (!leaf) return null;\n\n\tconst offset = boundary === 'start' ? 0 : getBlockLength(leaf);\n\treturn createCollapsedSelection(leafId, offset);\n}\n\n/**\n * Resolves a valid editor selection anywhere in the document, starting from\n * the first (or last) top-level block and deferring per-block resolution to\n * {@link createSelectionForBlockBoundary}. Useful as a last-resort fallback\n * after deletions when neighbouring siblings cannot provide a selection.\n *\n * @param state The editor state to query.\n * @param boundary `'start'` walks document order; `'end'` walks reverse.\n * @param excludeBlockId Optional block id to skip (e.g. the block about to\n * be removed by the caller's transaction).\n * @returns A valid selection, or `null` if no selectable block exists.\n */\nexport function createSelectionForDocumentBoundary(\n\tstate: EditorState,\n\tboundary: 'start' | 'end',\n\texcludeBlockId?: BlockId,\n): EditorSelection | null {\n\tconst children: readonly ChildNode[] = state.doc.children;\n\tconst indices: readonly number[] =\n\t\tboundary === 'start'\n\t\t\t? children.map((_, i) => i)\n\t\t\t: children.map((_, i) => children.length - 1 - i);\n\n\tfor (const i of indices) {\n\t\tconst child = children[i];\n\t\tif (!child || !isBlockNode(child)) continue;\n\t\tif (excludeBlockId !== undefined && child.id === excludeBlockId) continue;\n\n\t\tconst sel = createSelectionForBlockBoundary(state, child.id, boundary);\n\t\tif (sel) return sel;\n\t}\n\n\treturn null;\n}\n\n/** Returns the root-level block IDs in document order. */\nexport function getRootBlockIds(doc: Document): readonly BlockId[] {\n\treturn doc.children.map((child) => child.id);\n}\n","/**\n * Block insertion utilities for paste/clipboard operations and block-object\n * commands (table, image, horizontal rule, display formula).\n *\n * Provides context resolution (parent path, anchor index, empty detection)\n * for inserting blocks into the document tree — both at root level and\n * inside table cells — plus the shared primitive that drops a block-level\n * object onto its own line. Also contains pure helpers for block cloning,\n * recursive lookup, and attribute sanitization against a NodeSpec.\n */\n\nimport { canContain } from '../model/ContentModel.js';\nimport type { ContentSlice, SliceBlock } from '../model/ContentSlice.js';\nimport {\n\ttype BlockAttrArrayValue,\n\ttype BlockAttrValue,\n\ttype BlockAttrs,\n\ttype BlockNode,\n\ttype ChildNode,\n\ttype ContentSegment,\n\ttype InlineNode,\n\ttype Mark,\n\ttype TextNode,\n\tcreateBlockNode,\n\tcreateInlineNode,\n\tgenerateBlockId,\n\tgetBlockLength,\n\tgetBlockText,\n\tinlineSegment,\n\tisBlockNode,\n\tsegmentsToInlineChildren,\n\ttextSegment,\n} from '../model/Document.js';\nimport { normalizeHTMLId } from '../model/HTMLUtils.js';\nimport { findNodePath } from '../model/NodeResolver.js';\nimport type { AttrSpec } from '../model/NodeSpec.js';\nimport type { RichBlockData, RichSegment } from '../model/RichBlockData.js';\nimport type { SchemaRegistry } from '../model/SchemaRegistry.js';\nimport type { EditorSelection } from '../model/Selection.js';\nimport { isGapCursor, isNodeSelection } from '../model/Selection.js';\nimport type { BlockId, NodeTypeName } from '../model/TypeBrands.js';\nimport { inlineType, nodeType } from '../model/TypeBrands.js';\nimport type { EditorState } from '../state/EditorState.js';\nimport { isVoidBlock } from '../state/NavigationQueries.js';\nimport type { TransactionBuilder } from '../state/Transaction.js';\nimport { extractParentPath, findSiblingIndex, getSiblings } from './CommandHelpers.js';\n\n/**\n * Resolved insertion target within the document tree.\n * Contains everything needed to insert blocks at a specific anchor position.\n */\nexport interface InsertionContext {\n\treadonly parentPath: readonly BlockId[];\n\treadonly anchorIndex: number;\n\treadonly isAnchorEmpty: boolean;\n}\n\n/**\n * Resolves an insertion context for root-level (or nested-parent-level) insertion.\n * Computes the parent path, anchor index among siblings, and whether the anchor is empty.\n */\nexport function resolveRootInsertionContext(\n\tstate: EditorState,\n\tanchorBlockId: BlockId,\n\tschemaRegistry?: SchemaRegistry,\n): InsertionContext | undefined {\n\tconst path: readonly string[] | undefined = findNodePath(state.doc, anchorBlockId);\n\tconst parentPath: BlockId[] = extractParentPath(path);\n\n\tconst siblings: readonly ChildNode[] = getSiblings(state, parentPath);\n\tconst anchorIndex: number = findSiblingIndex(siblings, anchorBlockId);\n\tif (anchorIndex < 0) return undefined;\n\n\tconst isAnchorEmpty: boolean = isBlockEmpty(state, anchorBlockId, schemaRegistry);\n\treturn { parentPath, anchorIndex, isAnchorEmpty };\n}\n\n/**\n * Resolves an insertion context within a table cell.\n * The parent path points to the cell itself; siblings are the cell's children.\n */\nexport function resolveCellInsertionContext(\n\tstate: EditorState,\n\tanchorBlockId: BlockId,\n\tcellId: BlockId,\n\tschemaRegistry?: SchemaRegistry,\n): InsertionContext | undefined {\n\tconst cellPath: BlockId[] | undefined = findNodePath(state.doc, cellId) as BlockId[] | undefined;\n\tif (!cellPath) return undefined;\n\n\tconst cell: BlockNode | undefined = state.getBlock(cellId);\n\tif (!cell) return undefined;\n\n\tconst anchorIndex: number = cell.children.findIndex(\n\t\t(c) => isBlockNode(c) && c.id === anchorBlockId,\n\t);\n\n\tconst isAnchorEmpty: boolean = isBlockEmpty(state, anchorBlockId, schemaRegistry);\n\treturn { parentPath: cellPath, anchorIndex, isAnchorEmpty };\n}\n\n/**\n * Finds a table_cell ancestor for the given block.\n * Walks the node path upward, returning the first table_cell BlockId found.\n */\nexport function findTableCellAncestor(state: EditorState, blockId: BlockId): BlockId | undefined {\n\tconst block: BlockNode | undefined = state.getBlock(blockId);\n\tif (block?.type === 'table_cell') return blockId;\n\n\tconst path: BlockId[] | undefined = findNodePath(state.doc, blockId) as BlockId[] | undefined;\n\tif (!path) return undefined;\n\n\tfor (const id of path) {\n\t\tconst node: BlockNode | undefined = state.getBlock(id as BlockId);\n\t\tif (node?.type === 'table_cell') return id as BlockId;\n\t}\n\treturn undefined;\n}\n\n/**\n * Resolves the anchor block ID from the current editor selection.\n * Handles text selection, node selection, and gap cursor uniformly.\n */\nexport function resolveAnchorBlockId(selection: EditorSelection): BlockId {\n\tif (isNodeSelection(selection)) return selection.nodeId;\n\tif (isGapCursor(selection)) return selection.blockId;\n\treturn selection.anchor.blockId;\n}\n\n/**\n * Inserts a block node after the anchor position, resolving cell vs root context.\n * Removes the anchor block if it is empty (matching standard paste behavior).\n * Returns true on success, false if context resolution fails.\n */\nexport function insertBlockAfterAnchor(\n\tstate: EditorState,\n\tbuilder: TransactionBuilder,\n\tanchorBlockId: BlockId,\n\tblock: BlockNode,\n\tselection: EditorSelection,\n\tschemaRegistry?: SchemaRegistry,\n): boolean {\n\tconst cellId: BlockId | undefined = findTableCellAncestor(state, anchorBlockId);\n\n\tif (cellId) {\n\t\tconst ctx: InsertionContext | undefined = resolveCellInsertionContext(\n\t\t\tstate,\n\t\t\tanchorBlockId,\n\t\t\tcellId,\n\t\t\tschemaRegistry,\n\t\t);\n\t\tif (!ctx) return false;\n\n\t\tconst insertIndex: number = ctx.anchorIndex + 1;\n\t\tbuilder.insertNode(ctx.parentPath, insertIndex, block);\n\n\t\tif (ctx.isAnchorEmpty && ctx.anchorIndex >= 0) {\n\t\t\tbuilder.removeNode(ctx.parentPath, ctx.anchorIndex);\n\t\t}\n\t} else {\n\t\tconst ctx: InsertionContext | undefined = resolveRootInsertionContext(\n\t\t\tstate,\n\t\t\tanchorBlockId,\n\t\t\tschemaRegistry,\n\t\t);\n\t\tif (!ctx) return false;\n\n\t\tconst insertOffset: number = isGapCursor(selection) && selection.side === 'before' ? 0 : 1;\n\t\tbuilder.insertNode(ctx.parentPath, ctx.anchorIndex + insertOffset, block);\n\n\t\tif (ctx.isAnchorEmpty && !isGapCursor(selection)) {\n\t\t\tbuilder.removeNode(ctx.parentPath, ctx.anchorIndex);\n\t\t}\n\t}\n\n\treturn true;\n}\n\n/**\n * Document-root index of the top-level block that contains `blockId` — the block\n * itself when it already lives at the document root. Returns -1 when the block is\n * not part of the document. Block-level objects always live at the root, so an\n * insertion triggered from inside a container (e.g. a table cell) escapes to the\n * top level via this lookup.\n */\nexport function topLevelBlockIndex(state: EditorState, blockId: BlockId): number {\n\tconst path: readonly string[] | undefined = findNodePath(state.doc, blockId);\n\tconst topId: BlockId = path && path.length > 0 ? (path[0] as BlockId) : blockId;\n\treturn state.doc.children.findIndex((b) => b.id === topId);\n}\n\n/**\n * True when a container of `containerType` may hold every block in `blocks`,\n * per its {@link import('../model/NodeSpec.js').NodeSpec} content rule. An\n * undefined `containerType` denotes the document root, which imposes no\n * restriction. Used to keep paste from creating schema-invalid nesting, such as\n * a `table` dropped into a `table_cell` (#166).\n */\nexport function canContainerHoldBlocks(\n\tregistry: SchemaRegistry,\n\tcontainerType: string | undefined,\n\tblocks: readonly BlockNode[],\n): boolean {\n\tif (!containerType) return true;\n\treturn blocks.every((block) => canContain(registry, containerType, block.type));\n}\n\n/**\n * Insertion context that escapes to the document root: blocks are placed after\n * the top-level ancestor of `anchorBlockId` (e.g. the outer table when the caret\n * sits inside a cell). The anchor is never treated as empty, so the originating\n * container keeps its own content. Returns undefined when the anchor is not part\n * of the document.\n */\nexport function resolveRootEscapeContext(\n\tstate: EditorState,\n\tanchorBlockId: BlockId,\n): InsertionContext | undefined {\n\tconst topIndex: number = topLevelBlockIndex(state, anchorBlockId);\n\tif (topIndex === -1) return undefined;\n\treturn { parentPath: [], anchorIndex: topIndex, isAnchorEmpty: false };\n}\n\n/**\n * True when the block is a blank-line paragraph. Inline-aware: a paragraph that\n * holds only an atomic inline node (e.g. an inline formula) has width > 0 and is\n * therefore never treated as blank, so it is never silently removed.\n */\nexport function isEmptyParagraph(block: BlockNode): boolean {\n\treturn block.type === 'paragraph' && getBlockLength(block) === 0;\n}\n\n/**\n * Places a block-level object on its own line at the document root: the object\n * followed by a trailing empty paragraph, so a void/atomic object always has an\n * editable line after it. The object is inserted after the top-level ancestor of\n * the current selection; when that ancestor is a blank-line paragraph it is\n * consumed, so the object is never preceded by a stray empty paragraph (#152).\n *\n * Only an empty *paragraph* is consumed — an empty heading or list item is\n * deliberate structure — and the emptiness test is inline-aware (see\n * {@link isEmptyParagraph}). This is intentionally stricter than\n * {@link insertBlockAfterAnchor}, which the paste pipeline uses with a text-only\n * emptiness notion.\n *\n * A void anchor (image, display formula) already owns a trailing empty paragraph\n * as its escape line. In that case the object is placed before that paragraph and\n * the paragraph is reused as the object's trailing line, so a second blank line\n * never stacks up (#158).\n *\n * Selection is the caller's concern, since objects differ (a cursor inside a new\n * table vs. a node selection on an image or display formula). Returns the\n * trailing paragraph after the object, or undefined when the selection has no\n * resolvable anchor.\n */\nexport function insertBlockObjectOnOwnLine(\n\tstate: EditorState,\n\tbuilder: TransactionBuilder,\n\tanchorBlockId: BlockId,\n\tobject: BlockNode,\n): BlockNode | undefined {\n\treturn insertBlockObjectsOnOwnLines(state, builder, anchorBlockId, [object]);\n}\n\n/**\n * Places a sequence of block-level objects on their own lines at the document\n * root, sharing a single trailing empty paragraph. Generalizes\n * {@link insertBlockObjectOnOwnLine} for inserting several objects at once (e.g.\n * pasting two or more standalone formulas, #159); for a single object the two\n * behave identically. The anchor-consumption (#152) and void-anchor trailing\n * reuse (#158) rules apply once, around the whole run.\n *\n * Returns the trailing paragraph after the last object, or undefined when the\n * anchor or object list is empty.\n */\nexport function insertBlockObjectsOnOwnLines(\n\tstate: EditorState,\n\tbuilder: TransactionBuilder,\n\tanchorBlockId: BlockId,\n\tobjects: readonly BlockNode[],\n): BlockNode | undefined {\n\tif (objects.length === 0) return undefined;\n\n\tconst topIndex: number = topLevelBlockIndex(state, anchorBlockId);\n\tif (topIndex === -1) return undefined;\n\n\tconst anchor: BlockNode | undefined = state.doc.children[topIndex];\n\tconst following: BlockNode | undefined = state.doc.children[topIndex + 1];\n\n\tlet insertAt: number = topIndex + 1;\n\tfor (const object of objects) {\n\t\tbuilder.insertNode([], insertAt, object);\n\t\tinsertAt++;\n\t}\n\n\t// A void anchor already owns a trailing empty paragraph as its escape line;\n\t// reuse it so a second blank line never stacks up (#158). Otherwise add one.\n\tconst reusableTrailing: BlockNode | undefined =\n\t\tanchor && isVoidBlock(state, anchor.id) && following && isEmptyParagraph(following)\n\t\t\t? following\n\t\t\t: undefined;\n\tlet trailing: BlockNode;\n\tif (reusableTrailing) {\n\t\ttrailing = reusableTrailing;\n\t} else {\n\t\ttrailing = createBlockNode(nodeType('paragraph'));\n\t\tbuilder.insertNode([], insertAt, trailing);\n\t}\n\n\t// Drop a blank-line paragraph anchor so the objects are not preceded by a\n\t// stray empty paragraph (#152).\n\tif (anchor && isEmptyParagraph(anchor)) {\n\t\tbuilder.removeNode([], topIndex);\n\t}\n\n\treturn trailing;\n}\n\n/** Recursively clones a block tree, assigning new IDs to all block nodes. */\nexport function cloneBlockWithNewIds(block: BlockNode, newId: BlockId): BlockNode {\n\tconst children = block.children.map((child) => {\n\t\tif (isBlockNode(child)) {\n\t\t\treturn cloneBlockWithNewIds(child, generateBlockId());\n\t\t}\n\t\treturn child;\n\t});\n\treturn createBlockNode(block.type, children, newId, block.attrs, block.htmlId);\n}\n\n/** Recursively searches a block tree for a block with the given ID (DFS). */\nexport function findBlockRecursive(block: BlockNode, blockId: BlockId): BlockNode | undefined {\n\tif (block.id === blockId) return block;\n\tfor (const child of block.children) {\n\t\tif (!isBlockNode(child)) continue;\n\t\tconst found: BlockNode | undefined = findBlockRecursive(child, blockId);\n\t\tif (found) return found;\n\t}\n\treturn undefined;\n}\n\n/**\n * Validates incoming attributes against the declared AttrSpec.\n * Only declared keys are kept. Block callers may opt into immutable flat arrays\n * for specs that explicitly set `allowArray`; all other structured values fall\n * back to defaults or are removed.\n */\nexport function sanitizeAttrs(\n\tincoming: Record<string, unknown> | undefined,\n\tspecAttrs: Readonly<Record<string, AttrSpec>> | undefined,\n\tallowStructured = false,\n): BlockAttrs | undefined {\n\tif (!specAttrs) return undefined;\n\n\tconst result: Record<string, BlockAttrValue> = {};\n\tlet hasKeys = false;\n\n\tfor (const key of Object.keys(specAttrs)) {\n\t\tconst spec: AttrSpec = specAttrs[key] as AttrSpec;\n\t\tconst raw: unknown = incoming?.[key];\n\n\t\tif (\n\t\t\ttypeof raw === 'string' ||\n\t\t\t(typeof raw === 'number' && Number.isFinite(raw)) ||\n\t\t\ttypeof raw === 'boolean'\n\t\t) {\n\t\t\tresult[key] = raw;\n\t\t} else if (allowStructured && spec.allowArray && isBlockAttrArray(raw)) {\n\t\t\tresult[key] = Object.freeze([...raw]);\n\t\t} else if (spec.default !== undefined) {\n\t\t\tresult[key] = spec.default;\n\t\t}\n\t\tif (key in result) hasKeys = true;\n\t}\n\n\treturn hasKeys ? result : undefined;\n}\n\nfunction isBlockAttrArray(value: unknown): value is readonly BlockAttrArrayValue[] {\n\treturn (\n\t\tArray.isArray(value) &&\n\t\tvalue.every(\n\t\t\t(item: unknown): boolean =>\n\t\t\t\titem === null ||\n\t\t\t\ttypeof item === 'string' ||\n\t\t\t\ttypeof item === 'boolean' ||\n\t\t\t\t(typeof item === 'number' && Number.isFinite(item)),\n\t\t)\n\t);\n}\n\n/** Checks whether a block is empty (has no text and is not a void block). */\nfunction isBlockEmpty(\n\tstate: EditorState,\n\tblockId: BlockId,\n\tschemaRegistry?: SchemaRegistry,\n): boolean {\n\tconst block: BlockNode | undefined = state.getBlock(blockId);\n\tif (!block) return false;\n\n\tconst spec = schemaRegistry?.getNodeSpec(block.type);\n\treturn !spec?.isVoid && getBlockText(block) === '';\n}\n\n// --- Rich block creation ---\n\n/**\n * Validates a rich block against the schema registry.\n * Returns undefined for blocks with unknown types; sanitizes attributes\n * against the declared spec.\n */\nexport function validateRichBlockData(\n\traw: RichBlockData,\n\tschemaRegistry?: SchemaRegistry,\n): RichBlockData | undefined {\n\tif (!raw.type) return undefined;\n\tif (!schemaRegistry) return raw;\n\n\tconst spec = schemaRegistry.getNodeSpec(raw.type);\n\tif (!spec) return undefined;\n\n\tconst attrs: BlockAttrs | undefined = sanitizeAttrs(raw.attrs, spec.attrs, true);\n\tconst htmlId: string | undefined = normalizeHTMLId(raw.htmlId);\n\tconst segments: RichSegment[] | undefined = raw.segments\n\t\t? sanitizeRichSegments(raw.segments, schemaRegistry)\n\t\t: undefined;\n\tconst { htmlId: _rawHTMLId, ...rest } = raw;\n\treturn {\n\t\t...rest,\n\t\t...(htmlId ? { htmlId } : {}),\n\t\t...(attrs ? { attrs } : {}),\n\t\t...(segments ? { segments } : raw.segments ? { segments: [] } : {}),\n\t};\n}\n\n/**\n * Creates a BlockNode from validated rich block data.\n * Converts segments or plain text into inline children.\n */\nexport function createBlockFromRichData(blockData: RichBlockData): BlockNode {\n\tconst newId: BlockId = generateBlockId();\n\tconst children: readonly (TextNode | InlineNode)[] | undefined =\n\t\tcreateChildrenFromRichBlock(blockData);\n\tconst attrs: BlockAttrs | undefined = blockData.attrs\n\t\t? (blockData.attrs as BlockAttrs)\n\t\t: undefined;\n\n\treturn createBlockNode(\n\t\tnodeType(blockData.type) as NodeTypeName,\n\t\tchildren,\n\t\tnewId,\n\t\tattrs,\n\t\tblockData.htmlId,\n\t);\n}\n\n/**\n * Creates inline children from rich block data.\n * Uses mark-preserving segments when available, falls back to plain text.\n * Returns undefined for content-free blocks (e.g. void blocks).\n */\nfunction createChildrenFromRichBlock(\n\tblockData: RichBlockData,\n): readonly (TextNode | InlineNode)[] | undefined {\n\tconst segments: readonly ContentSegment[] = richBlockToContentSegments(blockData);\n\tif (segments.length === 0) return undefined;\n\treturn segmentsToInlineChildren(segments);\n}\n\n/**\n * Converts rich block data into a paste {@link ContentSlice}. Blocks that fail\n * schema validation (unknown type or filtered attributes) are dropped, so the\n * resulting slice can be fed straight into the canonical paste strategy\n * ({@link import('./PasteCommand.js').pasteSlice}).\n */\nexport function richBlocksToSlice(\n\tblocks: readonly RichBlockData[],\n\tschemaRegistry?: SchemaRegistry,\n): ContentSlice {\n\tconst sliceBlocks: SliceBlock[] = [];\n\tfor (const raw of blocks) {\n\t\tconst blockData: RichBlockData | undefined = validateRichBlockData(raw, schemaRegistry);\n\t\tif (!blockData) continue;\n\t\tsliceBlocks.push(richBlockToSliceBlock(blockData));\n\t}\n\treturn { blocks: sliceBlocks };\n}\n\n/** Converts a single validated rich block into a {@link SliceBlock}. */\nfunction richBlockToSliceBlock(blockData: RichBlockData): SliceBlock {\n\tconst attrs: BlockAttrs | undefined = blockData.attrs\n\t\t? (blockData.attrs as BlockAttrs)\n\t\t: undefined;\n\treturn {\n\t\ttype: nodeType(blockData.type) as NodeTypeName,\n\t\t...(attrs ? { attrs } : {}),\n\t\tsegments: richBlockToContentSegments(blockData),\n\t};\n}\n\n/** Builds content segments from a rich block, falling back to plain text. */\nfunction richBlockToContentSegments(blockData: RichBlockData): readonly ContentSegment[] {\n\tif (blockData.segments && blockData.segments.length > 0) {\n\t\treturn richSegmentsToContentSegments(blockData.segments);\n\t}\n\tconst text: string = blockData.text ?? '';\n\treturn text ? [textSegment(text)] : [];\n}\n\n/** Converts rich segments into content segments (marked text and inline nodes). */\nfunction richSegmentsToContentSegments(\n\tsegments: readonly RichSegment[],\n): readonly ContentSegment[] {\n\tconst result: ContentSegment[] = [];\n\tfor (const seg of segments) {\n\t\tif (seg.kind === 'inline') {\n\t\t\tresult.push(\n\t\t\t\tinlineSegment(\n\t\t\t\t\tcreateInlineNode(\n\t\t\t\t\t\tinlineType(seg.inlineType),\n\t\t\t\t\t\tseg.attrs as Readonly<Record<string, string | number | boolean>> | undefined,\n\t\t\t\t\t),\n\t\t\t\t),\n\t\t\t);\n\t\t\tcontinue;\n\t\t}\n\t\tif (seg.text.length === 0) continue;\n\t\tconst marks: readonly Mark[] = seg.marks.map((m) => ({\n\t\t\ttype: m.type as Mark['type'],\n\t\t\t...(m.attrs ? { attrs: m.attrs as Mark['attrs'] } : {}),\n\t\t}));\n\t\tresult.push(textSegment(seg.text, marks));\n\t}\n\treturn result;\n}\n\nfunction sanitizeRichSegments(\n\tsegments: readonly RichSegment[],\n\tschemaRegistry: SchemaRegistry,\n): RichSegment[] {\n\tconst sanitized: RichSegment[] = [];\n\tfor (const segment of segments) {\n\t\tif (segment.kind === 'inline') {\n\t\t\tconst spec = schemaRegistry.getInlineNodeSpec(segment.inlineType);\n\t\t\tif (!spec) continue;\n\t\t\tconst attrs = sanitizeAttrs(segment.attrs, spec.attrs);\n\t\t\tsanitized.push({\n\t\t\t\tkind: 'inline',\n\t\t\t\tinlineType: segment.inlineType,\n\t\t\t\t...(attrs ? { attrs } : {}),\n\t\t\t});\n\t\t\tcontinue;\n\t\t}\n\t\tsanitized.push(segment);\n\t}\n\treturn sanitized;\n}\n"],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import{c as t,f as e,h as o,o as n,p as r}from"./Document-827l3P80.mjs";import{a as i,c,t as s}from"./NodeResolver-Dleih-8R.mjs";import{d as l,o as a,t as u,u as d}from"./Selection-HYoVFpAx.mjs";import{a as h}from"./TypeBrands-Ch9856Gb.mjs";import{c as m,o as p}from"./PluginHelpers-KDuTlmXm.mjs";import{n as g}from"./DomUtils-Bf7JLFlx.mjs";import{t as f}from"./ShortcutFormatting-TwiufqeV.mjs";function b(t,e){const o=t.getNodePath(e)?.[0];return o?t.doc.children.findIndex(t=>t.id===o):-1}function q(t,o,r,i){const c=l(r,t.getBlockOrder()),s=b(t,c.from.blockId),a=b(t,c.to.blockId);if(s<0||a<0)return null;const u=Math.min(s,a),d=Math.max(s,a),h=t.doc.children.slice(u,d+1),m=i??(()=>!0),p=[];let g=[],f=!1;const q=()=>{0!==g.length&&(p.push(n(o,g,e())),f=!0,g=[])};for(const e of h)m(e)?g.push(e):(q(),p.push(e));if(q(),!f)return null;const k=t.transaction("command");for(let e=d;e>=u;e--)k.removeNode([],e);return p.forEach((t,e)=>{k.insertNode([],u+e,t)}),k.setSelection(r),k.build()}function k(t,e){const o=t.getState();if(!d(o.selection))return!1;const n=o.selection;if(!a(n))return!1;const i=n.anchor.blockId,s=o.getParent(i);if(!s||"blockquote"!==s.type)return!1;const l=o.getBlock(i);if(!l)return!1;const u=o.getNodePath(s.id);if(!u)return!1;const h=c(o.doc,u);if(!h)return!1;const m=r(s),p=m.findIndex(t=>t.id===i);return!(p<0)&&e({state:o,quotePath:u,quoteParentPath:u.slice(0,-1),quoteIndex:h.index,child:l,childIndex:p,childCount:m.length,offset:n.anchor.offset})}var I={label:"Blockquote",tooltip:t=>`Blockquote (${t})`},x=/* #__PURE__ */Object.assign({"./locales/ar.ts":()=>import("./ar-sGZ-oZqB.mjs"),"./locales/de.ts":()=>import("./de-uKR7koQe.mjs"),"./locales/es.ts":()=>import("./es-DrJyl38L.mjs"),"./locales/fr.ts":()=>import("./fr-BRXUnq3R.mjs"),"./locales/hi.ts":()=>import("./hi-SECtQQzq.mjs"),"./locales/pt.ts":()=>import("./pt-Cv6q7x5x.mjs"),"./locales/ru.ts":()=>import("./ru-DSRv3_Rg.mjs"),"./locales/zh.ts":()=>import("./zh-DYD476c5.mjs")});async function v(t){return m(x,t,I)}var N={},P=class{id="blockquote";name="Blockquote";priority=35;config;locale;constructor(t){this.config={...N,...t}}async init(t){this.locale=await p(t,this.config.locale,I,v),t.registerStyleSheet("\n.notectl-content blockquote {\n\tmargin: 0;\n\tpadding: 2px 0;\n\tpadding-inline-start: 16px;\n\tborder-inline-start: 3px solid var(--notectl-blockquote-border, var(--notectl-border));\n\tbackground: var(--notectl-blockquote-bg, transparent);\n\tcolor: var(--notectl-blockquote-fg, inherit);\n\tmin-height: 1.6em;\n}\n"),this.registerNodeSpec(t),this.registerCommands(t),this.registerKeymap(t),!1!==this.config.inputRule&&this.registerInputRule(t),this.registerToolbarItem(t)}registerNodeSpec(t){t.registerNodeSpec({type:"blockquote",group:"block",content:{allow:["paragraph","heading","list_item","blockquote","horizontal_rule","code_block"],min:1},toDOM(t){const e=g("blockquote",t.id);return e.setAttribute("part","blockquote"),e},toHTML:(t,e)=>`<blockquote>${e||"<br>"}</blockquote>`,parseHTML:[{tag:"blockquote"}],sanitize:{tags:["blockquote"]}})}registerCommands(t){t.registerCommand("toggleBlockquote",()=>this.toggleBlockquote(t)),t.registerCommand("setBlockquote",()=>this.wrapInBlockquote(t))}registerKeymap(e){e.registerKeymap({"Mod-Shift->":()=>e.executeCommand("toggleBlockquote")}),function(e){e.registerKeymap({Enter:()=>function(e){return k(e,n=>{if("list_item"===n.child.type)return!1;if(n.childIndex!==n.childCount-1||o(n.child)>0)return!1;const r=t(),i=n.state.transaction("input");return 1===n.childCount?(i.removeNode(n.quoteParentPath,n.quoteIndex),i.insertNode(n.quoteParentPath,n.quoteIndex,r)):(i.removeNode(n.quotePath,n.childIndex),i.insertNode(n.quoteParentPath,n.quoteIndex+1,r)),i.setSelection(u(r.id,0)),e.dispatch(i.build()),!0})}(e),Backspace:()=>function(t){return k(t,e=>{if(0!==e.offset||0!==e.childIndex)return!1;if("list_item"===e.child.type)return!1;const o=e.state.transaction("input");return 1===e.childCount?(o.removeNode(e.quoteParentPath,e.quoteIndex),o.insertNode(e.quoteParentPath,e.quoteIndex,e.child)):(o.removeNode(e.quotePath,0),o.insertNode(e.quoteParentPath,e.quoteIndex,e.child)),o.setSelection(u(e.child.id,0)),t.dispatch(o.build()),!0})}(e)},{priority:"context"})}(e)}registerInputRule(t){t.registerInputRule({pattern:/^> $/,handler(t,o,r,i){const c=t.selection;if(!d(c))return null;if(!a(c))return null;const s=t.getBlock(c.anchor.blockId);if(!s||"paragraph"!==s.type)return null;const l=t.doc.children.findIndex(t=>t.id===s.id);if(l<0)return null;const u=n(h("blockquote"),[s],e());return t.transaction("input").removeNode([],l).insertNode([],l,u).deleteTextAt(c.anchor.blockId,r,r+2).setSelection(c).build()}})}registerToolbarItem(t){t.registerToolbarItem({id:"blockquote",group:"block",icon:'<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M6 17h3l2-4V7H5v6h3zm8 0h3l2-4V7h-6v6h3z"/></svg>',label:this.locale.label,tooltip:this.locale.tooltip(f("Mod-Shift->")),command:"toggleBlockquote",isActive:t=>!!d(t.selection)&&i(t.doc,t.selection.anchor.blockId,"blockquote")})}toggleBlockquote(t){const e=t.getState(),o=e.selection;if(!d(o))return!1;const n=i(e.doc,o.anchor.blockId,"blockquote")?function(t,e,o){const n=s(t.doc,o.anchor.blockId,e);if(!n||1!==n.path.length)return null;const i=t.doc.children.findIndex(t=>t.id===n.node.id);if(i<0)return null;const c=r(n.node),l=t.transaction("command");return l.removeNode([],i),c.forEach((t,e)=>{l.insertNode([],i+e,t)}),l.setSelection(o),l.build()}(e,h("blockquote"),o):q(e,h("blockquote"),o,this.isQuoteChild(t));return!!n&&(t.dispatch(n),!0)}wrapInBlockquote(t){const e=t.getState(),o=e.selection;if(!d(o))return!1;const n=q(e,h("blockquote"),o,this.isQuoteChild(t));return!!n&&(t.dispatch(n),!0)}isQuoteChild(t){const e=t.getSchemaRegistry(),o=new Set(e.getNodeSpec(h("blockquote"))?.content?.allow??[]);return t=>{if(o.has(t.type))return!0;const n=e.getNodeSpec(t.type)?.group;return void 0!==n&&o.has(n)}}};export{I as n,v as r,P as t};
2
+ //# sourceMappingURL=BlockquotePlugin-0bZSbkyo.mjs.map